一、今天学习目标
- 顺序查找
- 二分查找(折半查找)必考
- 插值查找、斐波那契查找(了解思路)
- 哈希查找
- 各种查找对比 + 适用场景
二、1. 顺序查找(线性查找)
逐个遍历,直到找到。
- 优点:不要求数组有序
- 缺点:慢 O (n)
cpp
int seqSearch(int arr[], int n, int key) {
for (int i = 0; i < n; i++) {
if (arr[i] == key)
return i;
}
return -1;
}
三、2. 二分查找(折半查找)⭐⭐⭐⭐⭐
必须有序!必须有序!必须有序!
思想:每次取中间,缩小一半查找范围。时间复杂度 O(log n)
cpp
// 二分查找(迭代版,最常用)
int binarySearch(int arr[], int n, int key) {
int l = 0, r = n - 1;
while (l <= r) {
int mid = l + (r - l) / 2; // 防溢出
if (arr[mid] == key)
return mid;
else if (arr[mid] < key)
l = mid + 1;
else
r = mid - 1;
}
return -1;
}
四、3. 插值查找
按比例猜位置:mid = l + (key - arr[l]) * (r - l) / (arr[r] - arr[l])
- 数据分布均匀时比二分更快
- 极端数据反而慢
五、4. 斐波那契查找
利用斐波那契数列分割区间思路接近二分,只是分割点不同。了解即可,面试基本不手写。
六、5. 哈希查找
通过哈希函数直接定位平均 O (1),无序也能查就是我们 day17 实现的哈希表。
七、完整测试代码
cpp
#include <stdio.h>
int seqSearch(int arr[], int n, int key) {
for (int i = 0; i < n; i++)
if (arr[i] == key) return i;
return -1;
}
int binarySearch(int arr[], int n, int key) {
int l = 0, r = n - 1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (arr[mid] == key) return mid;
else if (arr[mid] < key) l = mid + 1;
else r = mid - 1;
}
return -1;
}
void printRes(int pos, int key) {
if (pos != -1)
printf("找到 %d,下标:%d\n", key, pos);
else
printf("未找到 %d\n", key);
}
int main() {
int arr[] = {1, 3, 5, 7, 9, 11, 13};
int n = sizeof(arr)/sizeof(arr[0]);
int key = 7;
printRes(seqSearch(arr, n, key), key);
printRes(binarySearch(arr, n, key), key);
return 0;
}
运行结果:
找到 7,下标:3
找到 7,下标:3
八、查找算法对比表(面试背这个)
表格
| 查找 | 数据要求 | 时间复杂度 | 优点 |
|---|---|---|---|
| 顺序查找 | 无序有序均可 | O(n) | 简单,不挑数据 |
| 二分查找 | 必须有序 | O(log n) | 极快,最常用 |
| 插值查找 | 有序且分布均匀 | O(log log n) | 均匀数据更快 |
| 斐波那契查找 | 有序 | O(log n) | 适合嵌入式 |
| 哈希查找 | 无序 | O (1) 平均 | 最快,工程首选 |
九、今日小练习
有序数组:[2,4,6,8,10,12,14,16]
- 用二分查找找 10
- 用二分查找找 5
- 输出下标或 -1