顺序查找和折半查找

243 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

  • 线性表结构
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 + 1else high = mid - 1;
	}
	return -1; // 查找失败
}

分块查找

性质:块内无序,块间有序;块内只能顺序查找,块间顺序/折半查找

图解 在这里插入图片描述

假设长度n的查找表均匀分为b块,每块有s个记录,等概率

顺序查找ASL:(s^2^ + 2s + n) / 2s

折半查找ASL(向上取整):log2(b + 1) + (s + 1) / 2