1. 查找
查找也叫检索,是根据给定的某个值,在表中确定一个关键字等于给定值的记录或数据元素
查找表是由同一类型(属性)的数据元素(记录)组成的集合
2. 分类
第一种分法:根据对表的操作
(1) 静态查找表:仅对查找表进行查找操作,而不能改变的表
(2) 动态查找表:对查找表除进行查找操作外,可能还要进行向表中插入数据元素或删除表中数据元素的表
第二种分法:根据存储结构
(1) 顺序表
(2) 链表
静态查找表
3. 顺序查找:逐个进行记录的关键字和给定值的比较(平均查找长度 )
必须使用顺序查找的情况:
(1) 线性表为无序表
(2) 有序线性表,但采用的是链式存储结构
4. 折半查找:先去定待查记录的范围,然后逐步缩小范围直到找到或找不到该记录为止
折半查找只使用于顺序存储的有序表(平均查找长度 )
5. 斐波那契查找(根据斐波那契序列对表进行分割,平均查找性能优于折半查找,最坏差)
插值查找(只适用于关键字均匀分布的表,对表厂较大的顺序表,平均性能很好)
6. 静态树表的查找(有序表中各记录的查找概率不等)
7. 索引顺序表的查找:分块查找——索引表按关键字有序,查找表分块有序,所谓分块有序是指第二个子表中所有记录的关键字均大于第一个子表中的最大关键字
平均查找长度:
动态查找表
8. 二叉排序树:或者是一棵空树,或者其左子树上所有结点的值均小于根结点的值,其右子树上所有结点的值均大于根结点的值,二叉排序树又称二叉查找树
其特点是:树的结构不是一次生成的,而是在查找过程中,当树中不存在关键字等于给定值的结点时再进行插入,新插入的结点一定是一个新添加的叶子结点,并且是查找不成功时查找路径上访问的最后一个结点的左孩子或右孩子结点
中序遍历二叉排序树可得到一个关键字有序序列
二叉排序树既拥有类似于折半查找的性能,又采用了链表做存储结构,因此是动态查找表的一种适宜表示
删除一个结点:
(1) 若删除一个叶子结点,只需要修改其双亲结点的指针
(2) 若删除的结点只有左子树(或右子树),则令其左子树(或右子树)成为其双亲结点的左子树
(3) 若删除结点的左子树和右子树均不空,则令其左子树的根结点代替其位置,令其右子树成为其左子树最右结点的右子树,或者令其左子树的最右结点接替其位置(注意处理最右结点可能存在的左子树)
二叉排序树的查找性能:(和树的形态有关)
9. 平衡二叉树(AVL树):左子树和右子树的深度之差不超过1
假设由于在二叉排序树上插入结点而失去平衡的最小子树根节点的指针为*a,即a是离插入结点最近,且平衡因子绝对值超过1的祖先结点
(1) 在*a的左子树根节点的左子树上插入结点,导致的不平衡,需要进行一次向右的顺时针旋转操作——单向右旋(左左右)
(2) 在*a的右子树根节点的右子树上插入结点,导致的不平衡,需要进行一次向左的逆时针旋转操作——单向左旋(右右左)
(3) 在*a的左子树根节点的右子树上插入结点,导致的不平衡,需要进行两次旋转,先左后右——双向旋转(左右左右)
(4) 在*a的右子树根节点的左子树上插入结点,导致的不平衡,需要进行两次旋转,先右后左——双向旋转(右左右左)
平衡树查找的性能:
10. B-树和B+树
B-树是一种平衡的多路查找树,它在文件系统中很有用
B+树是应文件系统所需而出的一种B-树的变型树
11. 键树(又称数字查找树):它是一棵度>=2的树,树中的每个结点中不是包含一个或几个关键字,而是只含有组成关键字的符号;例如,若关键字是单词,则结点中只包含一个字母符号,这种树给某种类型关键字的表的查找带来方便
键树是有序树,同一层中兄弟结点之间依所含符号自左向右有序
键树的存储结构:
(1) 以树的孩子兄弟链表来表示键树(3个域,值,第一棵子树指针,向右兄弟指针),此时的键树又称为双链树(从上往下,从左往右,直到空仍不等,则不成功)
平均查找长度:
(2) 以树的多重链表表示键树,则树的每个结点中应含有d个指针域,此时的键树又称为Trie树,若从键树中某个结点到叶子结点的路径上每个结点都只有一个孩子,则可将该路径上所有结点“压缩”成一个“叶子节点”(叶子结点中存储关键字及指向记录的指针),Trie树中有两种结点:分支结点和叶子结点
Trie树上进行查找的过程为,从根结点出发,沿给定值相应的指针逐层向下,直到叶子结点,若叶子结点中的关键字和给定值相等,则查找成功,若分支结点中和给定值相应的指针为空,或叶子结点中的关键字和给定值不等,则不成功
哈希表
12. 基本思想:在记录的存储地址和它的关键字之间建立一个确定的对应关系,这样,不经过比较,一次存取就能得到所查元素的查找方法(对应关系:哈希函数)
13. 根据设定的哈希函数和冲突处理方法将一组关键字映射到一个有限的地址集(区间)上,并以关键字在地址集中的“像”作为记录在表中的存储位置,这种表便称为哈希表,这一映像过程称为哈希造表或散列,所得到的存储位置称为哈希函数或散列地址
14. 哈希函数的构造方法
(1) 直接定址法:取关键字或关键字的某个线性函数值为哈希地址
(2) 数字分析法:哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干位数组成哈希地址
(3) 平方取中法:平方后取中间几位
(4) 折叠法:将关键字分割为位数相同的几部分(最后一部分可以不同),然后取这几部分的叠加和(舍去进位)做为哈希地址——移位折叠和间界折叠
(5) 除留余数法:取关键字被某个不大于哈希表表长m的数p除后得到的余数
(6) 随机数法:通常关键字长度不等时采用此法较恰当
15. 处理冲突的方法
(1) 开放定址法:Hi = ( H(key) + di ) MOD m (往后找空间)
线性探测再散列、二次探测再散列、伪随机探测再散列
(2) 再哈希法:Hi = RHi(Key) ,RHi均是不同的哈希函数,当发生冲突时,计算另一个哈希函数地址,直到冲突不再发生
(3) 链地址法:关键字的同义词的记录存储在同一线性表中
(4) 建立一个公共溢出区:一旦冲突,都填入溢出区
16. 哈希表总结
(1) 虽然哈希表在关键字与记录的存储位置之间建立了直接映像,但由于冲突的产生,使得哈希表的查找过程仍然是一个给定值和关键字进行比较的过程
(2) 查找过程中需和给定值进行比较的关键字的个数取决于:哈希函数、处理冲突方法、哈希表的装填因子
折半查找算法
int link_IDcheck(int *a,int n,int LinkID)
{
int low,high,mid;
unsigned int key=LinkID;
low=0;
high=n-1;
while(low<=high)
{
mid = (low+high) / 2;
if(a[mid] == key)
{
return mid;
}
else if(key < a[mid])
{
high=mid-1;
}
else low=mid+1;
}
return NOTFIND;
}