写在前面
本文学习内容来自《算法图解》一书及百度百科内容
算法是一组完成任务的指令。任何代码片段都可视为算法。 —— 摘自《算法图解》[^footnote]
二分查找
以下内容摘自百度百科
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
问题思考
- 还记得我们上学的时候,假如你想要去词典中找“算法”是什么意思,我们会怎么做?
- 上课的时候,老师叫我们把书翻到146页的时候,你是怎么翻到的呢?
- 我们以前和同学一起玩过的猜数字游戏还记得怎么玩的了吗?
当我们去思考上面问题,我们是不是这样可以通过地毯式的搜索,去达到我们的目的,例如我们可以从词典的第一页开始找,总能找到“算法”;我们从书的第一页开始翻,在下课之前一定能够翻到146页;或者你给我的范围,我从最小的开始猜,“0,1,2,3,······97,98,99 。对啦!” 我总能猜到你心里想的数字。这种方式称其简单查找。
二分查找思路
- 如果我们换种思路去解决这个问题。我们把字典翻开,翻到中间,看下中间位置的拼音和我们的“suan”能不能够对应的上,如果不能,“suan”在这前面还是在这后面,我们继续的去对应的位置去翻看,最终会找到我们要找的“算法”。
- 我们把书直接翻到中间,280页,在280页之前的一侧,再翻到中间,147页。往前再翻一页,成功翻到老师指定的页数学习。
- 同学A没毛病说 :“0~100我随便想一个数,你来猜猜看?”,同学B很执着说:“好啊,我来了啊,0”,同学A没毛病说:“不对,小了”,“1”,“不对,小了”,“2”,“不对,小了”,“3”,“不对,小了”,“4”,同学A没毛病吼道:“滚,你赢了。”同学C二分哥:“我来试试,50”,“小了”,“75”,“大了”,“62”,“小了”,“68”,“大了”,“65”,“小了”,“66”,“bingo!”;
看到这估计大部分同学已经看懂了二分查找的核心实现思路了。那我们来看看具体的实现过程
前置条件
- 必须采用顺序存储结构。
- 必须按关键字大小有序排列。
这里面大家需要注意一下,二分查找的使用是有硬性的条件约束的,必须满足条件的数据才能够使用二分查找。
实现过程
首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
代码实现
为了方便大家学习和调试,这里列出Java 和 python的代码给大家参考。
Java
public static int dichotomy(int[] ints, int item) {
int start = 0;
int end = ints.length - 1;
while (start <= end) {
int mid = (start + end) >>> 2;
int guess = ints[mid];
if (guess == item) {
return mid;
} else if (guess > item) {
end = mid - 1;
} else {
start = mid + 1;
}
}
return -1;
}
python
def dichotomy(list, item):
low = 0
high = len(list) - 1
while low <= high:
mid = (low + high) // 2
guess = list[mid]
if guess == item:
return mid
elif guess > item:
high = mid - 1
else:
low = mid + 1
return None