| 项目 | 值 |
|---|---|
| 主题 | 顺序查找和折半查找 |
| 核心概念 | 从表的一端开始,逐个比较关键字 |
| 时间复杂度 | $O(\log_2 n)$、$O(\log_2\log_2 n)$、$O(\log_2 n)$、$O(n)$ |
| 难度 | ⭐⭐ |
| 重要性 | ⭐⭐⭐⭐⭐ |
从表的一端开始,逐个比较关键字。
int SeqSearch(SSTable ST, KeyType key) {
ST.elem[0].key = key; // 哨兵
int i = ST.length;
while (ST.elem[i].key != key)
i--;
return i; // 0表示查找失败
}
i >= 0int BinarySearch(SSTable ST, KeyType key) {
int low = 1, high = ST.length;
while (low <= high) {
int mid = (low + high) / 2;
if (ST.elem[mid].key == key)
return mid;
else if (ST.elem[mid].key < key)
low = mid + 1;
else
high = mid - 1;
}
return 0; // 查找失败
}
折半查找过程可以用判定树表示:
n 个结点的判定树:
low=1, high=n,mid = ⌊(1+n)/2⌋ 为根[1, mid-1][mid+1, n]有序表:1, 2, 3, 4, 5, 6, 7
4
/ \
2 6
/ \ / \
1 3 5 7
$n=7$ 的判定树:
$ASL = (1\times1 + 2\times2 + 4\times3) / 7 = \frac{17}{7} \approx 2.43$
n 个结点的折半查找判定树:
根据关键字分布自适应调整 mid:
$$mid = low + \frac{key - ST[low]}{ST[high] - ST[low]} \times (high - low)$$适用于均匀分布的数据。
利用斐波那契数列分割区间:
有序表:1, 3, 5, 7, 9, 11, 13, 15,查找 $key = 13$。
| 步骤 | low | high | mid | 比较 |
|---|---|---|---|---|
| 1 | 1 | 8 | 4 | 7 < 13 |
| 2 | 5 | 8 | 6 | 11 < 13 |
| 3 | 7 | 8 | 7 | 13 = 13 |
比较 3 次,找到!
有序表同上,查找 $key = 6$。
| 步骤 | low | high | mid | 比较 |
|---|---|---|---|---|
| 1 | 1 | 8 | 4 | 7 > 6 |
| 2 | 1 | 3 | 2 | 3 < 6 |
| 3 | 3 | 3 | 3 | 5 < 6 |
| 4 | 4 | 3 | - | low > high,失败 |
有序表:A, B, C, D, E, F, G, H, I(关键字 1–9)。
构造过程:
E(5)
/ \
B(2) G(7)
/ \ / \
A(1) C(3) F(6) H(8)
\ \
D(4) I(9)
| 查找方法 | 时间复杂度 | 要求 |
|---|---|---|
| 顺序查找 | $O(n)$ | 无 |
| 折半查找 | $O(\log_2 n)$ | 有序 + 顺序存储 |
| 插值查找 | $O(\log_2\log_2 n)$ | 均匀分布 |
| 斐波那契查找 | $O(\log_2 n)$ | 有序 + 顺序存储 |