- 线性表结构
typedef struct {
ElemType *elem;
int TableLen;
}SSTable;
顺序查找
顺序表和链表的结构都可以
简单顺序查找
时间复杂度:O(n)
折半查找的判定树必为平衡二叉树
- 没有哨兵的方式
需要判断数组越界的情况
int Search_Seq(SSTable ST, ElemType key) {
for(int i = 0; i < ST.TableLen && ST.elem[i] != key; i++) {
return i == ST.TableLen ? -1 : i; // 成功返回下标,失败返回-1
}
}
- 有哨兵的方式
不需要判断数组越界
若线性表中有n个数组,下标从0开始,0号为“哨兵”,因此最后一个元素的下标为n
int Search_Seq(SSTable ST, ElemType key) {
ST.elem[0] = key; // "0号哨兵"
for(int i = ST.TableLen; ST.elem[i] != key; --i) {
return i;
}
}
情况 | 平均查找长度(概率相同) |
---|---|
成功 | (n+1) / 2 |
失败 | n + 1 |
有序顺序查找
情况 | 平均查找长度(概率相同) |
---|---|
成功 | (n+1) / 2 |
失败 | n / (n + 1) |
折半查找
时间复杂度:O(log2n)
只适用于有序的顺序表,不能是链表,需要有随机存取的特性
判定树一定是一个平衡的二叉排序树,树高(向上取整):log2(n + 1)
判定树的右子树结点数 - 左子树结点数 = 0 / 1 (偶数个元素时为1,奇数个元素时为0)
平均查找长度ASL = [(n + 1) / n] log2(n + 1) - 1 ≈ log2(n + 1) - 1
int Binary_Search(SSTable ST, ElemType key) { // 升序,降序只需要改一下判断
int low = 0;
int high = ST.TableLen - 1;
int mid;
while(low <= high) {
mid = (low + high) / 2; // C语言自动向下取整
if(ST.elem[mid] == key)
return mid;
if(ST.elem[mid] < key)
low = mid + 1;
else high = mid - 1;
}
return -1; // 查找失败
}
分块查找
性质:块内无序,块间有序;块内只能顺序查找,块间顺序/折半查找
图解
假设长度n的查找表均匀分为b块,每块有s个记录,等概率
顺序查找ASL:(s2 + 2s + n) / 2s
折半查找ASL(向上取整):log2(b + 1) + (s + 1) / 2