数据结构中的查找算法详解:顺序查找与二分查找

文章目录

1. 查找算法

2. 顺序查找

2. 二分查找


1. 查找算法

查找算法是用于在数据集中定位特定元素的位置的算法。查找是计算机科学中一项基本操作,几乎在所有应用程序中都需要使用。例如,数据库查询、信息检索、字典查找等都涉及到查找操作。查找算法可以根据不同的需求和数据结构选择不同的实现方法,以达到高效、准确的目的。

顺序查找

原理:从数据集的起始位置开始,依次检查每个元素,直到找到目标元素或到达数据集末尾。

优点:实现简单。无需数据集有序。

缺点:查找效率较低,时间复杂度为O(n)。

二分查找

原理:在有序数据集中,通过反复将查找范围减半,逐步缩小搜索范围,直到找到目标元素或确定目标元素不存在。

优点

  • 查找效率较高,时间复杂度为O(log n)。
  • 适用于有序数据集。

缺点

  • 需要数据集有序。
  • 实现相对复杂。

2. 顺序查找

顺序查找,又称线性查找,是一种最基本的查找算法。它的工作原理非常简单,主要步骤如下:

  1. 从头开始遍历:从数据集的起始位置开始,依次检查每个元素。
  2. 比较目标:对于每个遍历到的元素,将其与目标元素进行比较。
  3. 查找成功:如果当前元素等于目标元素,则查找成功,返回当前元素的索引。
  4. 查找失败:如果遍历完整个数据集仍未找到目标元素,则查找失败,返回一个特殊的标识来表示未找到。

这种方法的优点在于简单直观,但对于大量数据来说,效率不高,因为它在最坏情况下需要检查每个元素。

伪代码

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

  1. 初始时,low = 0high = 7,计算mid = (0 + 7) / 2 = 3

    • 比较arr[3](即4)与目标5
    • 因为4 < 5,所以目标在右半部分,更新low = 4
  2. 下一步,low = 4high = 7,计算mid = (4 + 7) / 2 = 5

    • 比较arr[5](即6)与目标5
    • 因为6 > 5,所以目标在左半部分,更新high = 4
  3. 最后,low = 4high = 4,计算mid = (4 + 4) / 2 = 4

    • 比较arr[4](即5)与目标5
    • 因为5 == 5,查找成功,返回索引4

因此,目标元素5在数组中的索引是4

  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TENET-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值