第一次盲写二分查找的打脸

来源:互联网 发布:java面向对象实验总结 编辑:程序博客网 时间:2024/06/09 21:45

所谓的盲写,就是在百度百科上简单看了一眼二分查找的原理,在纸上画画伪码,一拍脑袋:哦,想清楚了,小菜一碟。然后下笔如有神,语法都不带检查的大笔一挥,得到第一版代码。

public static int doSearch(int[] arry, int target){                // because arry is ASC        if (target < arry[0] || target > arry[arry.length-1]) {            return -1;        }                int low_index = 0;        int high_index = arry.length-1;        int mid_index;                while (low_index < high_index) {            mid_index = low_index + (high_index - low_index)/2;            int mid_val = arry[mid_index];            if (target > mid_val) {                low_index = mid_index;                continue;            }                        if (target < mid_val) {                high_index = mid_index ;                continue;            }                        if (target == mid_val) {                return mid_index;            }        }                return -1;  }

low_index = mid_index + 1

单元测试一测,一个测试方法一直出不来,代码运算量并不大,果断有死循环。这也给自己提了个醒,测试方法应加上timeout。Debug一下,发现死循环发生在测试下边界值处。原来第一处打脸的地方是在 low_index = mid_index 。

原因分析一下是,当对low_index和high_index之间的区域折半时,得到的一半值mid_index永远会偏向low_index,也就是:恰好有中间整数,得到的就是中间值;如果没有中间整数值,则滑向最接近的低位整数。如果low_index和high_index刚好相差1,mid_index的计算结果一直等于low_index,循环陷在将mid_index的计算结果为low_index然后再赋给low_index中出不来。

因此,low_index = mid_index修改为low_index = mid_index + 1,同时high_index = mid_index - 1。这本身也是折半的原理所在:折半对比,目标大于半数值,从高于折半处截取重新查找(low_index = mid_index + 1);目标小于半数值,从低于折半处截取重新查找(high_index = mid_index - 1);总之不相等则丢弃折半处


while (low_index < =high_index)

当使用while (low_index < high_index),对于数组长度为5或者6时,索引处1的值查找不出来。原因在于最后一次折半前,高低位重合,跳出循环,而来不及计算mid_index。


最后的写法,通过测试

public static int doSearch(int[] arry, int target){                // because arry is ASC        if (target < arry[0] || target > arry[arry.length-1]) {            return -1;        }                int low_index = 0;        int high_index = arry.length-1;        int mid_index;                while (low_index < =high_index) {            mid_index = low_index + (high_index - low_index)/2;            int mid_val = arry[mid_index];            if (target > mid_val) {                low_index = mid_index + 1;                continue;            }                        if (target < mid_val) {                high_index = mid_index - 1;                continue;            }                        if (target == mid_val) {                return mid_index;            }        }                return -1;}


0 0
原创粉丝点击