二分查找(一) 常见错误
2016-12-12 15:50
281 查看
每次遇到二分查找心中都是莫名的恐惧,因为我从来没有写对过。。。
错误一
可以看到,元素1,4,7是查找不到的。
错误原因是什么呢?
可以看到当left = right = 1时,不满足while(left < right),退出循环,返回-1.如果继续循环,此时mid = (left + right) / 2= 1,而array[mid] = value,mid就是我们要查找的。
所以我们试着把循环条件改为while (left <= right), 此时的运行结果 如下
序列内的元素都能够查找到了,现在尝试一下查找序列外的元素
可以看到查找-1时,最后一次循环left = 0,right = -1,不满足left <= right,跳出循环返回-1。
在查找20时,虽然最终返回-1,但是出现了数组越界的情况。
所以觉得上面的改法不太好
第二种改法
运行结果如下
所有的元素都查找到了
从图中可以看到第二种改法,不会出现left = right的情况。
现在尝试一下查找序列外的元素
错误二 死循环
简单的测试
看不都查找到了吗?
接着看下面
当查找的元素不在序列内,程序进入死循环
每一次循环都是left = right,而循环条件while (left <= right),一直死循环下去。
还有一个死循环的例子,下面
错误原因也是一样的,就不贴运行结果了
引用如下:
把二分查找算法写正确需要注意的地方
注:本人正在学习状态,文中多有引用,也有解释纰漏之处,敬请包涵、指正!
错误一
#include <stdio.h> #define SIZE(a) sizeof(a) / sizeof(a[0]) int search(int array[], int n, int v) { int left, right, mid; left = 0, right = n; while (left < right) { mid = (left + right) / 2; if (array[mid] > v) { right = mid - 1; } else if (array[mid] < v) { left = mid + 1; } else { return mid; } } return -1; } int main() { int array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 13, 19 }; int m = search(array, SIZE(array), 4); printf("m = %d\n", m); return 0; }
可以看到,元素1,4,7是查找不到的。
错误原因是什么呢?
可以看到当left = right = 1时,不满足while(left < right),退出循环,返回-1.如果继续循环,此时mid = (left + right) / 2= 1,而array[mid] = value,mid就是我们要查找的。
所以我们试着把循环条件改为while (left <= right), 此时的运行结果 如下
序列内的元素都能够查找到了,现在尝试一下查找序列外的元素
可以看到查找-1时,最后一次循环left = 0,right = -1,不满足left <= right,跳出循环返回-1。
在查找20时,虽然最终返回-1,但是出现了数组越界的情况。
所以觉得上面的改法不太好
第二种改法
int search(int array[], int n, int v) { int left, right, middle; left = 0, right = n; while (left < right) { middle = (left + right) / 2; if (array[middle] > v) { right = middle; // <---看这里 } else if (array[middle] < v) { left = middle + 1; } else { return middle; } } return -1; }
运行结果如下
所有的元素都查找到了
从图中可以看到第二种改法,不会出现left = right的情况。
现在尝试一下查找序列外的元素
错误二 死循环
int search(int array[], int n, int v) { int left, right, mid; left = 0, right = n - 1; while (left <= right) { mid = (left + right) / 2; if (array[mid] > v) { right = mid; } else if (array[middle] < v) { left = mid + 1; } else { return mid; } } return -1; }
简单的测试
看不都查找到了吗?
接着看下面
当查找的元素不在序列内,程序进入死循环
每一次循环都是left = right,而循环条件while (left <= right),一直死循环下去。
还有一个死循环的例子,下面
int search(int array[], int n, int v) { int left, right, mid; left = 0, right = n - 1; while (left <= right) { mid = (left + right) / 2; if (array[mid] > v) { right = mid; } else if (array[mid] < v) { left = mid; } else { return mid; } } return -1; }
错误原因也是一样的,就不贴运行结果了
引用如下:
把二分查找算法写正确需要注意的地方
注:本人正在学习状态,文中多有引用,也有解释纰漏之处,敬请包涵、指正!
相关文章推荐
- 二分查找错误事例分析
- 常见几个排序源码及二分查找源码
- 二分查找中的堆栈溢出错误
- js实现常见的几种算法(数组去重、字符统计、二分查找等)
- 第十题 二分查找 还是有好多错误
- 面试常见5个算法套装,4个排序+二分查找
- [LeetCode 278] First Bad Version(二分查找的一个常见注意点)
- LeetCode 374 使用循环代替递归的二分查找从而避免栈溢出的错误
- 使用std::lower_bound和std::upper_bound解决常见的二分查找问题
- 编程之美3.11 二分查找常见问题
- 常见几种二分查找
- 常见对象_二分查找使用的注意事项
- 二分查找及其常见类型
- STL 二分查找抛出错误(map/set iterator not dereferencable)
- 面试中常见的数组的操作:遍历,最值,反转,冒泡排序,二分查找(附代码)
- 常见错误(从混淆后的异常日志中查找问题)
- 常见查找算法之—二分查找
- Java实现的两种常见简单查找算法示例【快速查找与二分查找】
- 常见对象_数组高级二分查找原理图解
- C#中可以消除常见且浪费时间的C和C++错误的修改