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 代码

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

相关推荐
ZPC82103 分钟前
【无标题】
人工智能·pytorch·算法·机器人
2301_764441335 分钟前
使用python构建的STAR实验ΛΛ̄自旋关联完整仿真
开发语言·python·算法
Rainy Blue8839 分钟前
前缀和与差分(蓝桥杯高频考点)
数据结构·算法·蓝桥杯
Dfreedom.9 分钟前
机器学习经典算法全景解析与演进脉络(无监督学习篇)
人工智能·学习·算法·机器学习·无监督学习
421!15 分钟前
ESP32学习笔记之GPIO
开发语言·笔记·单片机·嵌入式硬件·学习·算法·fpga开发
夏日听雨眠19 分钟前
数据结构(单循环链表)
数据结构·链表
智算菩萨23 分钟前
【How Far Are We From AGI】4 AGI的“生理系统“——从算法架构到算力基座的工程革命
论文阅读·人工智能·深度学习·算法·ai·架构·agi
福赖25 分钟前
《算法:生产车间》
算法
空空潍34 分钟前
LeetCode力扣 hot100一刷完结
算法·leetcode
leaves falling37 分钟前
搜索插入位置(第一个≥target的位置)
算法