从零开始学算法----二分查找

顺序查找?

所谓顺序查找,就是从第一个元素开始,遍历表中的元素,以找到对应的节点

对于线性表来说, 如果该表是无序表, 那么不管它采用的是顺序存储还是链式存储, 都必须使用顺序查找。

如果该表是有序的,但是采用链式存储, 也必须使用顺序查找

当该表有序且顺序存储时, 我们可以采用二分查找

二分查找?

所谓二分查找就是说,针对一个有序数组,我们先取数组的中间值和要查找的目标值比较,如果比目标值大,就在左边的一半中查找,查找方式还是先取中间值比较。。。

从零开始学算法----二分查找

 

 这样对于一个长度为n的有序数组, 查找一个数所花费的时间最多为log2n

如长度为8的数组,最多3次就可以定位到

 1 /**
 2      * 使用二分查找在array数组中查询target的位置
 3      * @param array
 4      * @param startIndex
 5      * @param endIndex
 6      * @param target
 7      * @return
 8      */
 9     private static int binarySearch(int[] array, int startIndex, int endIndex, int target) {
10         int low = startIndex;
11         int high = endIndex-1;
12         while (low<=high) {
13             //取中间
14             int middle = (low + high)>>1;
15             int midValue = array[middle];
16             //如果中间值比target小, 就在右边查找
17             if (midValue < target) {
18                 //移动低位指针到middle+1的位置
19                 //+1是为了避免重复查找,因为Middle位置其实已经比较过了,相等的话就会返回
20                 //另外,如果不加1, 每次都会重复查找一个数据,那么最后剩下2个数据时,如array[10], array[11], 
21                 //要查找array[11], low = 10, high = 11, 那么middle=10,low=middle进入死循环
22                 low = middle+1;
23             } else if (midValue > target) {
24                 //移动高位指针到middle-1的位置
25                 high = middle-1;
26             } else {
27                 return middle;
28             }
29         }
30         //通常返回最后一次查找的低位指针的位置 
31         return -(low+1);
32     }
1 public static void main(String[] args) {
2         int[] array = {4,7,8,10,14,21,22,36,62,77,81,91};
3         int index = binarySearch(array, 0, array.length, 91);
4         System.out.println(index);
5     }

 

网上流传一种说法: 90%的程序员都写不出没有Bug的二分查找

其实这里的问题在于

int middle = (low + high)>>1;

这一行,如果low和high的值很大,可能会有内存溢出的问题 

所以我们修改这一行代码为:
int middle = low + ((high-low)>>1);

注意,由于移位运算的优先级较低, 要用括号括起来

 

上一篇:2021-10-20:二分查找


下一篇:二叉树寻找(定义例题)