文章目录
[1. 查找算法](#1. 查找算法)
[2. 顺序查找](#2. 顺序查找)
[2. 二分查找](#2. 二分查找)
1. 查找算法
查找算法是用于在数据集中定位特定元素的位置的算法。查找是计算机科学中一项基本操作,几乎在所有应用程序中都需要使用。例如,数据库查询、信息检索、字典查找等都涉及到查找操作。查找算法可以根据不同的需求和数据结构选择不同的实现方法,以达到高效、准确的目的。
顺序查找
原理:从数据集的起始位置开始,依次检查每个元素,直到找到目标元素或到达数据集末尾。
优点:实现简单。无需数据集有序。
缺点:查找效率较低,时间复杂度为O(n)。
二分查找
原理:在有序数据集中,通过反复将查找范围减半,逐步缩小搜索范围,直到找到目标元素或确定目标元素不存在。
优点:
- 查找效率较高,时间复杂度为O(log n)。
- 适用于有序数据集。
缺点:
- 需要数据集有序。
- 实现相对复杂。
2. 顺序查找
顺序查找,又称线性查找,是一种最基本的查找算法。它的工作原理非常简单,主要步骤如下:
- 从头开始遍历:从数据集的起始位置开始,依次检查每个元素。
- 比较目标:对于每个遍历到的元素,将其与目标元素进行比较。
- 查找成功:如果当前元素等于目标元素,则查找成功,返回当前元素的索引。
- 查找失败:如果遍历完整个数据集仍未找到目标元素,则查找失败,返回一个特殊的标识来表示未找到。
这种方法的优点在于简单直观,但对于大量数据来说,效率不高,因为它在最坏情况下需要检查每个元素。
伪代码
function linearSearch(array, target):
for index from 0 to length(array) - 1:
if array[index] == target:
return index // 查找成功,返回索引
return -1 // 查找失败,返回特殊标识
C代码实现
#include <stdio.h>
// 顺序查找函数
// arr[]: 待查找的数组
// n: 数组的长度
// target: 目标元素
int linearSearch(int arr[], int n, int target) {
// 遍历数组中的每个元素
for (int i = 0; i < n; i++) {
// 如果当前元素等于目标元素
if (arr[i] == target) {
return i; // 查找成功,返回当前元素的索引
}
}
return -1; // 查找失败,返回特殊标识 -1 表示未找到目标元素
}
int main() {
int arr[] = {3, 5, 7, 9, 11, 13, 15}; // 定义一个整数数组
int n = sizeof(arr) / sizeof(arr[0]); // 计算数组的长度
int target = 9; // 定义目标元素
// 调用顺序查找函数查找目标元素
int result = linearSearch(arr, n, target);
// 根据查找结果输出相应的信息
if (result != -1) {
printf("元素 %d 在数组中的索引为: %d\n", target, result); // 查找成功
} else {
printf("元素 %d 不在数组中\n", target); // 查找失败
}
return 0; // 程序结束
}
- 函数定义 :
linearSearch
函数接收一个数组、数组长度和目标元素作为参数。 - 遍历数组 :使用
for
循环遍历数组中的每个元素。 - 比较元素:在循环中,将每个元素与目标元素进行比较。如果相等,则返回当前索引。
- 查找失败:如果循环结束后仍未找到目标元素,则返回 -1 表示查找失败。
- 主函数 :在
main
函数中,定义了一个数组和目标元素,调用linearSearch
函数,并根据返回结果输出相应的信息。
2. 二分查找
二分查找(Binary Search)是一种高效的查找算法,通常用于在有序数据集中查找目标元素。其原理是通过将数据集划分为两半并与目标进行比较,以确定目标在哪一半中,从而逐步缩小搜索范围,直到找到目标元素或确定不存在目标元素。基本原理如下:
1. 选择中间元素:在有序数据集中,选择数组的中间元素。
- 初始时,选择整个数组的中间元素。对于一个有序数组
arr
,如果当前的搜索范围是[low, high]
,则中间元素的位置是mid = (low + high) / 2
。
2. 比较目标:将中间元素与目标元素进行比较。
- 将数组中间位置的元素
arr[mid]
与目标元素target
进行比较。
3. 查找成功:如果中间元素等于目标元素,则查找成功,返回中间元素的索引。
- 如果
arr[mid] == target
,则找到目标元素,返回mid
。
4. 缩小搜索范围:
- 对于一个升序的数据集,如果中间元素大于目标元素,说明目标可能在左半部分;如果中间元素小于目标元素,说明目标可能在右半部分。根据比较结果,将搜索范围缩小到左半部分或右半部分,继续查找。
- 如果
arr[mid] > target
,则目标元素在左半部分,即更新搜索范围为[low, mid - 1]
。 - 如果
arr[mid] < target
,则目标元素在右半部分,即更新搜索范围为[mid + 1, high]
。
5. 重复步骤:重复上述步骤,不断将搜索范围缩小,直到找到目标元素或搜索范围为空。
- 重复上述步骤,直到
low > high
(搜索范围为空)或找到目标元素。
C代码实现
#include <stdio.h>
// 二分查找函数
int binarySearch(int arr[], int low, int high, int target) {
while (low <= high) {
int mid = (low + high) / 2; // 选择中间元素
if (arr[mid] == target) {
return mid; // 查找成功,返回索引
} else if (arr[mid] > target) {
high = mid - 1; // 缩小搜索范围到左半部分
} else {
low = mid + 1; // 缩小搜索范围到右半部分
}
}
return -1; // 查找失败,返回特殊值
}
int main() {
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
int n = sizeof(arr) / sizeof(arr[0]);
int target = 5;
int result = binarySearch(arr, 0, n - 1, target);
if (result != -1) {
printf("Element found at index: %d\n", result);
} else {
printf("Element not found in array\n");
}
return 0;
}
- 时间复杂度 :二分查找的时间复杂度是
O(log n)
,因为每次比较后搜索范围都会减少一半。 - 空间复杂度 :由于二分查找只需要几个额外的变量存储索引,因此空间复杂度是
O(1)
。
假设我们有一个有序数组arr = {1, 2, 3, 4, 5, 6, 7, 8}
,目标元素是5
。
-
初始时,
low = 0
,high = 7
,计算mid = (0 + 7) / 2 = 3
。- 比较
arr[3]
(即4
)与目标5
。 - 因为
4 < 5
,所以目标在右半部分,更新low = 4
。
- 比较
-
下一步,
low = 4
,high = 7
,计算mid = (4 + 7) / 2 = 5
。- 比较
arr[5]
(即6
)与目标5
。 - 因为
6 > 5
,所以目标在左半部分,更新high = 4
。
- 比较
-
最后,
low = 4
,high = 4
,计算mid = (4 + 4) / 2 = 4
。- 比较
arr[4]
(即5
)与目标5
。 - 因为
5 == 5
,查找成功,返回索引4
。
- 比较
因此,目标元素5
在数组中的索引是4
。