第七章——查找
第七章——查找
一、查找的基本概念有:
(1)查找表
(2)关键字
(3)查找
(4)动态查找表和静态查找表
(5)平均查找长度
二、线性表的查找
1、顺序查找
(1)数据类型定义
typedef KeyType int;//这个根据具体情况去定义;在这里定义为int; typedef struct{ KeyType key; InfoType otherinfo;//这个根据具体情况去改,这里只是抽象的说成还要添加这些类型。 }ElemType; typedef struct{ ElemType *R; int length; }SSTable;
(2)顺序查找
int Search_Seq(SSTable ST,KeyType key) {//在顺序表ST中顺序查找其关键字等于Key的数据元素。若找到,则函数值为该元素在表中的位置,否则为0; for(int i = ST.length ; i >= 1 ;i--) { if(ST.R[i].key==key) return i;//从后往前找; return 0; } }
2、折半查找(顺序存储切表中关键字有序)
其代码为
int Search_Bin(SSTable ST,KeyType key) //在顺序表ST中顺序查找关键字等于key的数据 元素。若找到,则函数值为该元素在表中的位 置,若找不到则为0 { low=1;high=ST.length; //置查找区间初值 while(low<=high) { mid=(low+high)/2; if(key==ST.R[mid].key) return mid; //找到待查找元素 else if(key<ST.R[mid].key) high=mid-1; //继续在前一子表进行查找 else low=mid+1; //继续在后一子表进行查找 } return 0; }
三、树表的查找
1、二叉排序树的查找:
BSTNode* Search(BSTree t ,KeyType x) //定义函数 { if(t==NULL)return NULL; if(t->data.key==x) return t; if(t->data.key>x) return Search(t->lchild,x); if(t->data.key<x) return Search(t->rchild,x); }
2、平衡二叉树:左子树和右子树的深度之差的绝对值不超过1; 左子树和右子树也是平衡二叉树。
3、B-树和B+树: B-树解决了数据量大时的查找,而B+树则在B-树的基础上解决了区间查找问题。
四、散列表的查找
1、主要研究问题
(1)如何构造散列函数
(2)如何处理冲突
2、好的散列函数的规则
(1)函数计算要简单,每一关键字只能由一个散列地址与之对应
(2)函数的值域须在表长的范围内,计算出的散列地址的分布应均匀,尽可能减少冲突
3、方法:
①数字分析法——必须明确知道所有关键字每一位上的各种数字的分布情况。实际应用:同意出版社的图书,ISBN前几位相同,用数字分析法时,排除ISBN的前几位
②平方取中法——适用于 不了解关键字的所有情况,或难于直接从关键字中找到取值比较分散的几位 的情况
③折叠法——散列地址位数较少,关键字位数较多,且难于直接从关键字中找到取值比较分散的几位
④除留取余法——H(key) = key%p p一般取小于表长的最大质数
实际应用过程中,冲突很难完全避免处理冲突的方法:
① 开放地址法 Hi=(H(key)+di)%m
Ⅰ 线性探测法 di=1,2,3,……,m-1
Ⅱ 二次探测法 di=1²,-1²,2²,-2²,3²,……,+k²,-k² (k<=m/2)
Ⅲ 伪随机探测法 注意将造表时的随机序列记录,用于查表
② 链地址法
把具有相同散列地址的记录放在同一个单链表中,m个散列地址就有m个单链表,同时用HT[0…m-1]存放链表的头指针,凡是散列地址为i的记录都以结点方式插入到以HT[i]为头节点的单链表中
五、总结:
这个章节的难度并不大,更注重于逻辑上的分析,只要能将各种问题分好类,然后用恰当的方法去解决,就不会有什么大的问题。在学习中遇到最大的问题就是概念越来越多了,可能会因此混淆,然后对自己的记忆产生影响。对于之前的目标,我感觉现在自己打代码的能力有所提升,希望以后的能力能更进一步。