数据结构简记--7

第 7 章 查找

7.1 查找的定义

查找:在数据集合中寻找满足某种条件的数据元素的过程。

查找表:用于查找的数据集合成为查找表,它由同一类型的数据元素(或记录)组成。

关键字:数据元素中唯一标识该元素的某个数据项的值,使用关键字的查找,查找结果是唯一的。

平均查找长度(ASL,Average Search Length):所有查找过程中进行关键字的比较次数的平均值。

7.2 顺序查找

typedef struct{		//查找表的数据结构(顺序表) 
	int *elem;	    //动态数组基地址 
	int TableLen;   //表的长度 
}SSTable;

//顺序查找 
int Search_Seq(SSTable st,int key)
{
	int i;
	for(i=0;i<st.TableLen&&st.elem[i]!=key;i++);
	//查找成功,则返回元素下标;查找失败,则返回-1 
	return i==st.TableLen?-1:i;
}

int main() {
	int i;
	SSTable L; //定义一个顺序表变量 
	L.elem = (int*)malloc(sizeof(int)*100); //初始动态分配 
	L.TableLen=0;  //初始化表长度
	//利用循环给顺序表赋值 
	for(i=0;i<10;i++)
	{
		L.elem[i]=i;
		L.TableLen+=1;
	}
	//打印顺序表中的元素 
	for(i=0;i<10;i++)
		printf("%4d",L.elem[i]);
	printf("\n");
	//查找指定元素在顺序表中的位置,并打印出其在顺序表中的下标 
	printf("%d\n",Search_Seq(L,5));
	printf("%d\n",Search_Seq(L,15));
	return 0;
}

运行结果:

7.3 折半查找

仅适用于有序的顺序表。

//折半查找
int Binary_Search(SSTable st,int key)
{
	int low=0,high=st.TableLen-1,mid;
	while(low<=high){
		mid=(low+high)/2;          //取中间位置 
		if(st.elem[mid]==key)
			return mid;			   //查找成功则返回 元素所在位置 
		else if(st.elem[mid]>key)
			high=mid-1;			   //从前半部分继续查找 
		else
			low=mid+1;			   //从后半部分继续查找 
	}
		return -1;			       //查找失败,返回-1 
}

7.4 分块查找

//顺序表
typedef struct{		//查找表的数据结构(顺序表) 
	int *elem;	    //动态数组基地址 
	int TableLen;   //表的长度 
}SSTable;
//索引表
typedef struct{ 
	int maxValue; // 索引区间的最大键值
	int low,high; // 索引区间的起止下标 
}Index; 
//索引表数组
typedef struct{
	Index *ind; //动态索引表数组基地址	
	int TableLen;   //表的长度
}IndexList;
//分块查找
int Block_Search(SSTable st, IndexList sy, int key)
{
	int i, j;
	//顺序查找索引表
//    for (i = 0; i < sy.TableLen; i++)
//    {
//    	if (key <= sy.ind[i].maxValue)
//            break;	
//	}
   //折半查找索引表 	
	int low = 0, high =sy.TableLen-1;
	while (low <= high)
	{
	    int mid = (low + high) / 2;
	    if (key == sy.ind[mid].maxValue)
	    {
	        i = mid;
	        break;
	    }
	    else if (key < sy.ind[mid].maxValue)
	        high = mid - 1;
	    else
	        low = mid + 1;
	}
	if (low > high)
	    i = low;
	//超出索引表则查找失败
	if (i == sy.TableLen)
	    return -1; //查找失败返回-1 
	//在顺序表中索引表对应的块中查找 
    j = sy.ind[i].low;
    while (j <= sy.ind[i].high)
    {
        if (key == st.elem[j])
            break;
        else
            j++;
    }
    if (j <= sy.ind[i].high)
        return j;
    else
        return -1;
}

在main()中调用分块查找

int main() {
	SSTable L; //定义一个顺序表变量 
	L.elem = (int*)malloc(sizeof(int)*100); //初始动态分配 
	L.TableLen=14;  //初始化表长度
	L.elem[0]=7;
	L.elem[1]=10;
	L.elem[2]=13;
	L.elem[3]=19;
	L.elem[4]=16;
	L.elem[5]=20;
	L.elem[6]=27;
	L.elem[7]=22;
	L.elem[8]=30;
	L.elem[9]=40;
	L.elem[10]=36;
	L.elem[11]=43;
	L.elem[12]=50;
	L.elem[13]=48;
	IndexList SY;
	SY.ind = (Index*)malloc(sizeof(Index)*100); //初始动态分配 
	SY.TableLen=5;  //初始化表长度
	SY.ind[0].maxValue=10;
	SY.ind[0].low=0;
	SY.ind[0].high=1;
	SY.ind[1].maxValue=20;
	SY.ind[1].low=2;
	SY.ind[1].high=5;
	SY.ind[2].maxValue=30;
	SY.ind[2].low=6;
	SY.ind[2].high=8;
	SY.ind[3].maxValue=40;
	SY.ind[3].low=9;
	SY.ind[3].high=10;
	SY.ind[4].maxValue=50;
	SY.ind[4].low=11;
	SY.ind[4].high=13;
	printf("%d\n",Block_Search(L,SY,19));
	printf("%d\n",Block_Search(L,SY,30));
	printf("%d\n",Block_Search(L,SY,60));
	return 0;
}

数组赋值也可用定义的同时完成初始化的赋值,或键盘输入等赋值方式可使赋值过程更简便。

运行结果:

7.5 二叉查找树

//二叉查找树结点 
typedef struct BSTNode{
	int key;
	struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;
//二叉查找树
BSTree BST_Search(BSTree T,int key)
{
	while(T!=NULL&&key!=T->key)
	{
		if(key<T->key)
			T=T->lchild;
		else T=T->rchild;
	}
	return T;
	//使用递归 
//	if(T==NULL)
//		return NULL;
//	if(key==T->key)
//		return T;
//	else if(key<T->key)
//		return BST_Search(T->lchild,key);
//	else
//		return BST_Search(T->rchild,key);
}
int BST_Insert(BSTree *T,int k)
{
	if(*T==NULL)
	{
		*T=(BSTree)malloc(sizeof(BSTNode));
		(*T)->key=k;
		(*T)->lchild=(*T)->rchild=NULL;
		return 1;
	}
	else if(k==(*T)->key)
		return 0;
	else if(k<(*T)->key)
		return BST_Insert(&((*T)->lchild),k);
	else
		return BST_Insert(&((*T)->rchild),k);
}
int main() {
	BSTree T=NULL;
	BST_Insert(&T,19);
	printf("%d\n",T->key);
	BST_Insert(&T,13);
	BST_Insert(&T,11);	
	printf("%d\n",T->lchild->lchild->key);
	BST_Insert(&T,50);
	BST_Insert(&T,26);
	BST_Insert(&T,21);
	BST_Insert(&T,30);
	BST_Insert(&T,66);
	BST_Insert(&T,60);
	BST_Insert(&T,70);
	printf("%d\n",T->rchild->rchild->rchild->key);
	printf("%d\n",BST_Search(T,60)->key);
	return 0;
}

 运行结果:

7.6 散列查找(哈希表)

#include <stdio.h>
#include <stdlib.h>
#define HashSize 12
#define Empty -32767 //为空标记 
//哈希表 
typedef struct
{
	int *value;
	int hashsize;
}HashMap; 
//初始化 
void IntiHashMap(HashMap *H)
{
	int i;
	H->hashsize=HashSize; //初始化哈希表长度 
	H->value=(int *)malloc(HashSize*sizeof(int)); //创建哈希表数组 
	for(i=0;i<HashSize;i++) //初始化哈希表为空 
	{
		H->value[i]=Empty;
	} 
}
//散列函数 (除留余数法) 
int Hash(int value) 
{
	return value%HashSize; //除数也可换成其他更合适的值,如小于HashSize的最大质数 
}
//在哈希表中插入数据 
void Insert(HashMap *H,int data)
{
	int InsertAddress;
	InsertAddress=Hash(data);
	//发生冲突 
	while(H->value[InsertAddress]!=Empty)//线性探测 
	{
		InsertAddress=(InsertAddress+1)%HashSize;
	}
	H->value[InsertAddress]=data;
} 
//查找指定元素是否在哈希表中 
int Search(HashMap *H,int SeartData)
{
	int HashAddress;
	HashAddress=Hash(SeartData);	
	while(H->value[HashAddress]!=SeartData)
	{
		HashAddress=(HashAddress+1)%HashSize;
		if(H->value[HashAddress]==Empty||HashAddress==Hash(SeartData))
		{
			return -1;
		}
	}	
	return HashAddress;
}
int main() 
{
	HashMap H;
	int i;
	int a[12]={19,14,23,1,68,20,84,23,11,55,10,79};
	IntiHashMap(&H); 
	for(i=0;i<HashSize;i++)
	{
		Insert(&H,a[i]);
	}	
	printf("address ");
	for(i=0;i<HashSize;i++)
	printf("%6d",i);
	printf("\n");
	printf("a[i]    ");
	for(i=0;i<HashSize;i++)
	printf("%6d",a[i]);
	printf("\n");	
	printf("Hash[i] ");
	for(i=0;i<HashSize;i++)
	printf("%6d",H.value[i]);
	printf("\n");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值