C语言使用qsort和bsearch实现二分查找

引言

在计算机科学领域,查找是一项基本操作,而二分查找是一种高效的查找算法。本博客将详细解释一个简单的C语言程序,演示如何使用标准库函数qsortbsearch来对一个整数数组进行排序和二分查找。

代码解析

包含头文件

c 复制代码
#include <stdio.h>
#include <stdlib.h>

首先,我们包含了两个标准头文件,stdio.h用于输入输出操作,stdlib.h用于内存分配和其他一些杂项功能。

比较函数

c 复制代码
int compareIntegers(const void *a, const void *b) {
    return (*(int *)a - *(int *)b);
}

定义了一个比较函数compareIntegers,该函数用于在排序和二分查找时比较两个整数。这个函数的作用是返回a - b的值,即升序排序。

主函数

c 复制代码
int main() {
    // 创建已排序的整数数组
    int numbers[] = {101, 305, 248, 407, 109};
    int numNumbers = sizeof(numbers) / sizeof(numbers[0]);

    // 排序数组
    qsort(numbers, numNumbers, sizeof(numbers[0]), compareIntegers);

    // 设置要查找的 number
    int targetNumber = 305;

    // 使用bsearch搜索学生
    int *result = (int *)bsearch(&targetNumber, numbers, numNumbers, sizeof(numbers[0]), compareIntegers);

    // 检查结果并输出
    if (result != NULL) {
        printf("Number found: %d\n", *result);
    } else {
        printf("Number %d not found\n", targetNumber);
    }

    return 0;
}
创建并排序数组
c 复制代码
int numbers[] = {101, 305, 248, 407, 109};
int numNumbers = sizeof(numbers) / sizeof(numbers[0]);
qsort(numbers, numNumbers, sizeof(numbers[0]), compareIntegers);

在主函数中,我们首先创建了一个整数数组numbers,然后使用sizeof操作符计算数组元素个数。接下来,我们使用qsort函数对数组进行升序排序,传递了比较函数compareIntegers来定义排序顺序。

二分查找
c 复制代码
int targetNumber = 305;
int *result = (int *)bsearch(&targetNumber, numbers, numNumbers, sizeof(numbers[0]), compareIntegers);

设置要查找的目标数字为305,然后使用bsearch函数在已排序的数组中进行二分查找。同样,我们传递了比较函数compareIntegers来确保查找的一致性。

输出结果
c 复制代码
if (result != NULL) {
    printf("Number found: %d\n", *result);
} else {
    printf("Number %d not found\n", targetNumber);
}

最后,我们检查bsearch的结果。如果找到了目标数字,就输出找到的数字;否则,输出未找到的消息。

时间复杂度

让我们分析一下这个程序中排序和查找部分的时间复杂度:

  1. 排序 (qsort):

    • 时间复杂度:O(n * log(n))
      • qsort通常使用快速排序算法,其平均时间复杂度为O(n * log(n)),其中n是数组的元素个数。
      • 在这个程序中,numNumbers是5,所以排序的时间复杂度为O(5 * log(5))。
  2. 查找 (bsearch):

    • 时间复杂度:O(log(n))
      • bsearch使用二分查找算法,其时间复杂度为O(log(n)),其中n是数组的元素个数。
      • 在这个程序中,数组已经排好序,numNumbers是5,所以查找的时间复杂度为O(log(5))。

因此,整个程序的时间复杂度主要由排序的部分决定,为O(5 * log(5))。在大O表示法中,忽略常数项,这可以简化为O(log(5)),即O(1)。因此,总体时间复杂度可以近似看作是O(1),即常数时间。这意味着程序的运行时间与数组的规模无关,对于小规模的数组来说是非常高效的。

总结

这个简单的C程序演示了如何使用qsort对数组进行排序,然后使用bsearch进行二分查找。这两个函数是C标准库中用于排序和查找的强大工具,通过传递比较函数,我们可以适应不同的数据类型和排序/查找需求。在实际编程中,这种方法能够提高效率,并且是一种常见的编程实践。

相关推荐
Dovis(誓平步青云)11 分钟前
《滑动窗口算法:从 “暴力遍历” 到 “线性高效” 的思维跃迁》
运维·服务器·数据库·算法
_OP_CHEN37 分钟前
【算法基础篇】(五十七)线性代数之矩阵乘法从入门到实战:手撕模板 + 真题详解
线性代数·算法·矩阵·蓝桥杯·c/c++·矩阵乘法·acm/icpc
天天爱吃肉821842 分钟前
【跨界封神|周杰伦×王传福(陶晶莹主持):音乐创作与新能源NVH测试,底层逻辑竟完全同源!(新人必看入行指南)】
python·嵌入式硬件·算法·汽车
im_AMBER42 分钟前
Leetcode 114 链表中的下一个更大节点 | 删除排序链表中的重复元素 II
算法·leetcode
凉、介1 小时前
VMware 三种网络模式(桥接 / NAT / Host-Only)原理与实验解析
c语言·网络·笔记·操作系统·嵌入式·vmware
xhbaitxl1 小时前
算法学习day38-动态规划
学习·算法·动态规划
多恩Stone1 小时前
【3D AICG 系列-6】OmniPart 训练流程梳理
人工智能·pytorch·算法·3d·aigc
wangjialelele1 小时前
Linux中的进程管理
java·linux·服务器·c语言·c++·个人开发
历程里程碑1 小时前
普通数组----轮转数组
java·数据结构·c++·算法·spring·leetcode·eclipse
pp起床1 小时前
贪心算法 | part02
算法·leetcode·贪心算法