C语言查找算法对比分析

下面是对您提供的 C 语言代码的逐行详细分析、注释说明、功能解释 ,并附上程序流程图描述(可据此绘制图形化流程图)。


🧾 一、完整带注释的代码

复制代码
复制代码
#include <stdio.h>   // 标准输入输出库
#include <stdlib.h>  // 标准库(含 rand(), srand())
#include <time.h>    // 时间库(用于 time())

int main() {
    // 1. 初始化随机数种子:以当前时间作为种子,使每次运行产生不同随机序列
    srand(time(0));

    // 2. 定义一个长度为10的整型数组 arr,并初始化为全0
    int arr[10] = {0};

    // 3. 构造一个严格递增数组:
    //    arr[i] = arr[i-1] + (0~9 的随机数)
    //    因此 arr 是非递减(实际是严格递增,因为 rand()%10 >=0,且通常 >0)
    for (int i = 1; i < 10; i++) {
        arr[i] = arr[i - 1] + (rand() % 10);
    }

    // 4. 打印数组下标(0 到 9),每个占4字符宽度,并记录总打印字符数 len
    int len = 0;
    for (int i = 0; i < 10; i++) {
        len += printf("%4d", i);  // printf 返回打印的字符数(如 "   0" 是4个字符)
    }
    printf("\n");  // 换行

    // 5. 打印与上面下标等长的横线(用于分隔)
    for (int i = 0; i < len; i++) 
        printf("-");
    printf("\n");

    // 6. 打印数组 arr 的内容,每个元素占4字符宽度
    for (int i = 0; i < 10; i++) {
        printf("%4d", arr[i]);
    }
    printf("\n");

    // 7. 进入主循环:不断从标准输入读取整数 x,直到 EOF(如 Ctrl+D / Ctrl+Z)
    int x;
    while (scanf("%d", &x) != EOF) {

        // = 线性查找部分 =
        int cnt1 = 0, cnt2 = 0;      // 分别记录线性查找和二分查找的比较次数
        int flag1 = 0, flag2 = 0;    // 标记是否找到 x

        // 线性查找:从头到尾遍历 arr
        for (int i = 0; i < 10; i++) {
            cnt1++;                  // 每次循环都算一次比较
            if (arr[i] != x) continue;  // 若不等于 x,跳过
            flag1 = 1;               // 找到了!
            break;                   // 提前退出
        }

        // = 二分查找部分(要求 arr 有序,此处满足)=
        int l = 0, r = 9, mid;       // 左右边界 [0, 9]
        while (l <= r) {
            cnt2++;                  // 每次进入循环算一次比较
            mid = (l + r) >> 1;      // 等价于 (l + r) / 2,位运算更快

            if (arr[mid] == x) {
                // 找到目标值
                printf("(%d) arr[%d] = %d, find %d\n", cnt2, mid, arr[mid], x);
                flag2 = 1;
                break;
            } else if (arr[mid] > x) {
                // 中间值太大,搜索左半部分
                printf("(%d) arr[%d] = %d > %d, change [%d, %d] to [%d, %d]\n", 
                       cnt2, mid, arr[mid], x, l, r, l, mid - 1);
                r = mid - 1;
            } else {
                // 中间值太小,搜索右半部分
                printf("(%d) arr[%d] = %d < %d, change [%d, %d] to [%d, %d]\n", 
                       cnt2, mid, arr[mid], x, l, r, mid + 1, r);
                l = mid + 1;
            }
        }

        // 8. 输出两种查找的结果对比
        printf("flag1 = %d, cnt1 = %d\n", flag1, cnt1);  // 线性查找结果
        printf("flag2 = %d, cnt2 = %d\n", flag2, cnt2);  // 二分查找结果
    }

    return 0;
}

🔍 二、功能详解

✅ 程序整体目的:

演示并对比线性查找(Linear Search)与二分查找(Binary Search)在有序数组中的效率差异。

🔸 步骤分解:

  1. 生成一个长度为10的严格递增整数数组 arr

    • arr[0] = 0
    • arr[i] = arr[i-1] + (0~9 的随机数) → 保证 arr 单调不减(几乎总是严格递增)
  2. 美观地打印数组及其下标

    • 先打印下标 0 1 2 ... 9(每个占4列)
    • 再打印等长横线
    • 再打印数组值
  3. 循环读取用户输入的整数 x

    • 支持连续查询多个 x,直到输入结束(EOF)
  4. 对每个 x 执行两种查找:

    • 线性查找 :从 arr[0]arr[9] 逐个比对,记录比较次数 cnt1 和是否找到 flag1
    • 二分查找 :利用数组有序性,每次缩小一半搜索范围,记录比较次数 cnt2 和是否找到 flag2,并详细打印每一步的判断过程
  5. 输出两种方法的查找结果和比较次数

    • 便于直观感受二分查找的高效性(cnt2 通常远小于 cnt1

📊 三、关键设计亮点

特性 说明
随机但有序数组 srand(time(0)) 保证每次运行不同,但 arr 始终有序,适合二分查找
自动对齐打印 利用 printf 返回值计算总宽度,动态画横线,提升可读性
详细二分过程日志 清晰展示区间 [l, r] 如何变化,教学价值高
支持多轮查询 用户可连续输入多个数字测试,无需重启程序

🔄 四、程序流程图(文字描述)

可据此用 PlantUML / draw.io / Mermaid 绘制图形

复制代码
复制代码
开始
│
├─ 初始化随机种子 srand(time(0))
│
├─ 创建数组 arr[10] = {0}
│
├─ for i=1 to 9: arr[i] = arr[i-1] + rand()%10
│
├─ 打印下标 0~9(记录总宽度 len)
│
├─ 打印 len 个 '-'
│
├─ 打印数组 arr 的值
│
└─ 循环:while (scanf("%d", &x) != EOF)
     │
     ├─ 线性查找:
     │    cnt1=0, flag1=0
     │    for i=0 to 9:
     │        cnt1++
     │        if arr[i]==x → flag1=1, break
     │
     ├─ 二分查找:
     │    l=0, r=9, cnt2=0, flag2=0
     │    while l<=r:
     │        cnt2++
     │        mid = (l+r)/2
     │        if arr[mid]==x → 打印找到,flag2=1, break
     │        else if arr[mid]>x → r=mid-1,打印区间更新
     │        else → l=mid+1,打印区间更新
     │
     └─ 打印 flag1/cnt1 和 flag2/cnt2
│
结束(当输入 EOF 时)

流程图关键节点符号建议(按标准):

  • 椭圆:开始 / 结束
  • 矩形:处理(如赋值、计算)
  • 平行四边形:输入/输出(如 scanf, printf)
  • 菱形 :判断(如 arr[mid] == x?
  • 箭头:控制流

💡 五、示例运行(假设 arr 为 [0,3,7,12,15,19,24,28,33,37])

复制代码
复制代码
   0   1   2   3   4   5   6   7   8   9
----------------------------------------
   0   3   7  12  15  19  24  28  33  37
15
(1) arr[4] = 15 == 15, find 15
flag1 = 1, cnt1 = 5
flag2 = 1, cnt2 = 1

5
(1) arr[4] = 15 > 5, change [0, 9] to [0, 3]
(2) arr[1] = 3 < 5, change [0, 3] to [2, 3]
(3) arr[2] = 7 > 5, change [2, 3] to [2, 1]
flag1 = 0, cnt1 = 10
flag2 = 0, cnt2 = 3

可见:找 15 时,二分仅1次就命中;找不存在的 5,二分3次就确定不存在,而线性查了全部10次。


✅ 六、总结

这段代码是一个优秀的教学示例,它:

  • 展示了随机有序数组的构建
  • 实现了线性 vs 二分查找的对比
  • 提供了清晰的过程日志
  • 具备良好的交互性和可重复测试性

非常适合用于讲解算法效率、查找策略、C语言基础等内容。

如需生成图形化流程图,可使用以下 Mermaid 代码

希望这份分析对您理解代码有极大帮助!

相关推荐
辰阳星宇2 小时前
【工具调用】工具调用后训练参数设计方案总结
人工智能·算法·自然语言处理
被星1砸昏头2 小时前
自定义操作符高级用法
开发语言·c++·算法
2301_810540732 小时前
python第一次作业
开发语言·python·算法
Stardep2 小时前
算法入门19——二分查找算法——X的平方根
算法·leetcode·二分查找算法
We་ct2 小时前
LeetCode 135. 分发糖果:双向约束下的最小糖果分配方案
前端·算法·leetcode·typescript
宇钶宇夕2 小时前
CoDeSys入门实战一起学习(十三):函数(FUN)深度解析:自定义、属性与实操案例
运维·算法·自动化·软件工程
好奇龙猫2 小时前
【大学院-筆記試験練習:线性代数和数据结构(14)】
数据结构
l1t2 小时前
对clickhouse给出的二分法求解Advent of Code 2025第10题 电子工厂 第二部分的算法理解
数据库·算法·clickhouse
Tisfy2 小时前
LeetCode 3315.构造最小位运算数组 II:位运算
算法·leetcode·题解·位运算