查找算法笔记
查找
1、顺序查找和折半查找
1.1 顺序查找
1.1.1算法思想
思想:
从线性表的一端开始,与关键字逐个比较。
满足条件,则查找成功并返回该元素在线性表中的位置;
若已经比对到表的另一端还没有匹配成功,则返回查找失败信息
1.1.2算法代码实现
typedef struct{ //定义查找表的数据结构
ElemType *elem; //元素存储空间基址,建表时按实际长度分配,0号单元留空
Int TableLen; //表的长度
}SSTable;
int Search_Seq(SSTable ST , ElemType key){ //在顺序表ST中顺序查找关键字为key的元素。若查找成功则返回该元素的下表位置
ST.elem[0] = key ; //将0地址元素作为“哨兵”
for(int i = ST.TableLen; ST.elem[i] != key;--i)//若表中不存在关键字key,将查找的i为0是退出循环
return i;
}
引入哨兵目的是使得Search_Seq内的循环不必判断数组是否会越界,因为满足i==0时, 循环一定跳出
1.2 折半查找
1.2.1 算法思想
前提:
****仅适合有序的顺序表
****仅适合有序的顺序表
****仅适合有序的顺序表
思想:
首先将给定值key与表中中间元素的关键字比较,若相等,则查找成功,返回元素的存储位置;
若不等,则所需查找的元素只能在中间元素以外的前半部分或后半部分,然后在缩小的范围内继续进行同样的查找,如此往复,
直到查找成功为止或在表中找不到这样的元素,则查找失败,返回查找失败的原因。
1.2.2 算法代码实现
int Binary_Search(SeqList L , ElemKey key){ //非递归实现
int low = 0 , high = L.TableLen - 1, mid;
while(low <= high){
mid = (low +high)/2;
if(L.elem[mid] == key){
return mid;
} else if (key > L.elem[mid]){//key值在右侧
low = mid + 1;
}else{
high = mid - 1; //key在左侧
}
}
1.2.2 小总
对于折半查找:
- 如果是奇数个结点,则选取中间节点。
- 如果是偶数个结点,则从始至终用分界线靠左或靠右的结点。
1.3 分块查找(索引查找)
1.3.1 算法思想
前提:
“是顺序查找和折半查找的综合”
将查找表分成若干个子块。块内元素可以无序,但块之间是有序的(即第一个子块的最大关键字小于第二个字块的最小关键字,以此类推)。
再建一个索引表索引表中的每个元素含有各块的最大关键字和各块中的第一个元素的地址。索引表按关键字(各块最大元素)大小有序排列。
思想:
第一步:在索引表中确定key所在的块,可以顺序查找或折半查找索引表;
第二部:在块内顺序查找。
1.3.2 小总
1.3.2 算法代码实现
2、B树和B+树
2.1 B树(多路平衡查找树)及其基本操作
- B树的阶 :所有结点树孩子结点数的最大值,m来表示。
- 一棵m阶B树或为空树
1)树中每个结点至多有m棵子树(即最多有m-1个关键字)
2)若根节点不是终端节点,则至少有两棵子树。(根节点至少有一个关键字)
3)除根节点外的所有非叶节点至少有 ⌈ m 2 ⌉ \lceil \frac{m}{2} \rceil ⌈2m⌉棵子树(即至少含有 ⌈ m 2 − 1 ⌉ \lceil \frac{m}{2} -1\rceil ⌈2m−1⌉个关键字)
4)所有非叶节点的结构如下:
n | P0 | K1 | P1 | K2 | P2 | ··· | Kn | Pn |
---|
其中,n表示有多少个关键字Ki(i = 1,2,···,n)为结点的关键字,且满足 K1 < K2 < ···<Kn ; Pi为指向子树根节点的指针,且指针Pi-1所指子树中所有结点的关键字均小于Ki,Pi所指子树中所有结点的关键字均大于Ki,n为结点中关键字的个数。
5)所有叶节点都出现在同一层次上,并且不带信息(实际指向这些结点的指针为空,即不存在)
B树是所有结点的平衡因子都为0的多路查找树,上图为3阶B树,其中最低层表示叶节点,在这些结点中,没有存放任何信息。
2.1.1 B树的高度(磁盘存取次数)
1)高度 h ≥ log m n + 1 h\geq \log_m^{n+1} h≥logmn+1(n个关键字、m阶)
2.1.2 B树的查找
B树的查找与二叉树查找很相似,只是每个结点有多个关键字的有序表。
基本操作:
- 在B树中找结点;
- 在节点中找关键字。
由于前一个查找操作在磁盘上进行的,而后一个操作在内存中进行的,即在找到目标节点后应先将节点中的信息读入内存中
2.1.3 B树的插入
插入过程:
- 定位:
利用查找算法找到插入该关键字的最低层中的某个非叶节点(B树中的插入关键字一定插入在最低层中的某个非叶节点内) - 在B树中,每个非失败结点的关键字个数都在区间 [ ⌈ m 2 ⌉ , m − 1 ] [ \lceil \frac{m}{2} \rceil , m-1] [⌈2m⌉,m−1]内,
- 插入后的结点关键字个数小于m,可以直接插入;
- 插入后的结点关键字个数大于m-1时,必须对结点进行分裂。
分裂的方法:
- 取一个新结点,在插入key后的原节点,从中间位置将其中的关键字分为两部分,左部分包含的关键字放在原节点中,右部分包含的关键字放在新节点中,中间位置 ( ⌈ m 2 ⌉ ) (\lceil \frac{m}{2} \rceil) (⌈2m⌉)的结点插入到原来的父节点。
- 若导致父节点的关键字个数超过上限,则继续进行这种分裂操作,知道这个过程传到根节点为止,进而B树高度增1。
2.1.4 B树的删除
2.2 B+树的基本概念
3、散列表
4、串
5、补充
知识点一
静态查找 | 动态查找 |
---|---|
顺序查找、折半查找、散列查找 | 二叉排序树、散列查找 |
-
查找表: 用于查找的数据的集合(一般指某一数组或链表)
-
静态查找:仅涉及查询某一特定元素是否在查找表中
-
动态查找:需要动态的插入或删除查找表内元素
-
关键字:数据元素唯一标识该元素的某个数值项的值,基于关键字查找查找结果应该唯一。(例如,学生由学号、姓名等信息组成,其中‘学号’能够唯一的表示该生信息,则学号就是关键字)
-
平均查找长度(ASL):在查找过程中,一次查找的长度是指需要比较的关键字次数,而平均查找长度则是所有查找过程中进行关键字的比较次数的平均值。
A S L = ∑ i = 1 n P i C i ASL =\sum_{i=1}^{n}Pi Ci ASL=i=1∑nPiCi
Pi是查找第i个数据元素的概率,一般认为每个数据元素的查找概率相等,即Pi=1/n;Ci是找到第i个数据元素所需进行比较的次数。
知识点二
对线性的链表只能进行顺序查找。