查找
查找(Search)是指在一组数据中定位某个特定元素是否存在及其具体位置的过程,是几乎所有程序都会涉及的基础操作。
三种查找算法对比
查找算法复杂度对比 — 在 n=1000 时的操作次数
三种查找算法对比总结
线性查找 O(n)
不要求有序
逐一比较,简单可靠
适合:数据量小或无序
二分查找 O(log n)
要求有序
每次折半排除一半
适合:有序数据通用方案
插值查找 O(log log n)
要求有序+均匀分布
按值比例估算位置
适合:均匀分布时最优
线性查找
从第一个元素开始逐一比较,直到找到目标或遍历完毕。不要求数据有序,时间复杂度 O(n)。
二分查找
要求数据必须已排序。每次与中间元素比较,将查找范围折半缩小,时间复杂度 O(log n)。
插值查找
对二分查找的优化。不取中点,而是根据目标值估算其可能位置。数据分布均匀时可达 O(log log n)。
实例
#include <stdio.h>
/* 线性查找:O(n),不要求有序 */
int linearSearch(int arr[], int n, int target) {
for (int i = 0; i < n; i++) {
if (arr[i] == target) return i;
}
return -1;
}
/* 二分查找:O(log n),要求数组有序(升序) */
int binarySearch(int arr[], int left, int right, int target) {
while (left <= right) {
int mid = left + (right - left) / 2; /* 防溢出写法 */
if (arr[mid] == target) return mid; /* 找到了 */
if (arr[mid] < target)
left = mid + 1; /* 目标在右半部分 */
else
right = mid - 1; /* 目标在左半部分 */
}
return -1; /* 未找到 */
}
/* 插值查找:O(log log n) 平均,要求数据分布均匀 */
int interpolationSearch(int arr[], int n, int target) {
int low = 0, high = n - 1;
while (low <= high && target >= arr[low] && target <= arr[high]) {
/* 插值公式:根据值的大小比例估算位置 */
int pos = low + ((target - arr[low]) * (high - low))
/ (arr[high] - arr[low]);
if (arr[pos] == target) return pos;
if (arr[pos] < target)
low = pos + 1;
else
high = pos - 1;
}
return -1;
}
int main() {
int arr[] = {10, 20, 30, 40, 50, 60, 70, 80, 90};
int n = 9;
printf("线性查找 50: 索引 %d\n", linearSearch(arr, n, 50)); /* 输出: 4 */
printf("二分查找 50: 索引 %d\n", binarySearch(arr, 0, n-1, 50)); /* 输出: 4 */
printf("插值查找 50: 索引 %d\n", interpolationSearch(arr, n, 50)); /* 输出: 4 */
return 0;
}
/* 线性查找:O(n),不要求有序 */
int linearSearch(int arr[], int n, int target) {
for (int i = 0; i < n; i++) {
if (arr[i] == target) return i;
}
return -1;
}
/* 二分查找:O(log n),要求数组有序(升序) */
int binarySearch(int arr[], int left, int right, int target) {
while (left <= right) {
int mid = left + (right - left) / 2; /* 防溢出写法 */
if (arr[mid] == target) return mid; /* 找到了 */
if (arr[mid] < target)
left = mid + 1; /* 目标在右半部分 */
else
right = mid - 1; /* 目标在左半部分 */
}
return -1; /* 未找到 */
}
/* 插值查找:O(log log n) 平均,要求数据分布均匀 */
int interpolationSearch(int arr[], int n, int target) {
int low = 0, high = n - 1;
while (low <= high && target >= arr[low] && target <= arr[high]) {
/* 插值公式:根据值的大小比例估算位置 */
int pos = low + ((target - arr[low]) * (high - low))
/ (arr[high] - arr[low]);
if (arr[pos] == target) return pos;
if (arr[pos] < target)
low = pos + 1;
else
high = pos - 1;
}
return -1;
}
int main() {
int arr[] = {10, 20, 30, 40, 50, 60, 70, 80, 90};
int n = 9;
printf("线性查找 50: 索引 %d\n", linearSearch(arr, n, 50)); /* 输出: 4 */
printf("二分查找 50: 索引 %d\n", binarySearch(arr, 0, n-1, 50)); /* 输出: 4 */
printf("插值查找 50: 索引 %d\n", interpolationSearch(arr, n, 50)); /* 输出: 4 */
return 0;
}
复杂度对比总结
| 算法 | 时间复杂度 | 要求有序 | 适用场景 |
|---|---|---|---|
| 线性查找 | O(n) | 否 | 数据量小或无序 |
| 二分查找 | O(log n) | 是 | 有序数组,通用高效 |
| 插值查找 | O(log log n) 平均 | 是 | 数据分布均匀的特定场景 |
