二分法效率和for循环比较效

我们可以通过简单的分析来估算时间。假设单片机的主频为 48 MHz,执行一条指令的时钟周期为 1 / 48 MHz = 20.83 ns。接下来看代码中需要的指令数。

//假设代码如下:
for (int i = 0; i < 500; i++) {
    if (array[i] == 8) {
        // do something
    }
}

分析循环的指令数:

  1. 初始化循环变量 (int i = 0):1 条指令。

  2. 条件检查 (i < 500):1 条指令。

  3. 数组读取 (array[i]):1 条指令。

  4. 比较操作 (array[i] == 8):1 条指令。

  5. 循环变量自增 (i++):1 条指令。

  6. 跳转指令(回到条件检查):1 条指令。

对于每次迭代,总共需要 6 条指令。假设数组中没有早停条件(即必须遍历整个数组),遍历 500 个元素的总指令数为:

总时间计算:

执行 3000 条指令所需时间为:

3000 \times 20.83 , \text{ns} = 62.49 , \mu\text{s}

结论:

在 48 MHz 的单片机上,遍历一个长度为 500 的数组,并判断是否有值等于 8,大约需要 62.5 微秒。这个时间只是一个估算值,实际情况还会受到编译器优化、内存访问速度等因素的影响。

如果主频提高到 72 MHz,则时钟周期为:

T = \frac{1}{72 , \text{MHz}} = 13.89 , \text{ns}

指令数保持不变(仍为 3000 条指令),执行时间为:

3000 \times 13.89 , \text{ns} = 41.67 , \mu\text{s}

结论:

在 72 MHz 的单片机上,遍历一个长度为 500 的数组,并判断是否有值等于 8,大约需要 41.7 微秒

二分查找算法

时间复杂度为 ,对长度为 500 的数组,最多需要进行 多次比较。

假设数组已排序,代码如下:

int binarySearch(uint16_t array[], int size, uint16_t target) {
    int left = 0, right = size - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (array[mid] == target)
            return mid;
        else if (array[mid] < target)
            left = mid + 1;
        else
            right = mid - 1;
    }
    return -1;
}

分析每次迭代的指令数:

  1. 计算中间位置 (mid = left + (right - left) / 2):大约 3 条指令。

  2. 比较操作 (array[mid] == target):1 条指令。

  3. 判断分支更新:

若 array[mid] < target,更新 left = mid + 1,大约 1 条指令。

若 array[mid] > target,更新 right = mid - 1,大约 1 条指令。

  1. 循环条件检查 (left <= right):1 条指令。

每次迭代总指令数约为 7条。

最大指令数:

对于 9 次迭代,总指令数为:

9 \times 7 = 63 , \text{条指令}

在 72 MHz 下的总执行时间:

每条指令耗时 ,总时间为:

63 \times 13.89 , \text{ns} = 874.07 t{ns}

比较:
普通 for 循环:遍历 500 个元素,耗时约 41.7 µs。
二分查找:只需 874 ns,比普通循环快了近 50 倍。

结论:

如果数组是已排序的,使用二分查找在 72 MHz 的单片机上查找值为 8 的元素,耗时大约 874 纳秒,效率远高于普通循环。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值