二分查找教学(趣味图解算法之二分查找)

100次浏览     发布时间:2024-10-08 08:46:21    

大多数程序员在看到"算法"两字的时候,是不是头大如斗。但如果想去大公司发展,在面试时又绕不过算法这座大山。市面上好多讲解算法的书籍(如算法导论)基本上都太学术、太复杂,对初学者很不友好。


因此小编准备换了思路,通过图解方法来分析复杂的算法实现,让初学算法朋友们不会再感到那么枯燥。

今天小编为读者老爷们带来了第一篇趣味图解算法之二分查找。

1、 简介

二分查找也叫折半查找,意思每次查找后,查找范围都折半。使用该查找方法有个前提条件就是要查找的元素必须是有序排列的。下面我们就来看看具体实现过程吧!

2、 算法分析

如上图是一个顺序排列的数值元素列表,假定我们要查找图中值为19的元素,若使用普通的遍历方法,我们需要从第一个元素开始,将每一个元素与要查找的元素进行比较,直到找到对应元素值与要查找的元素值相等为止。使用这种方法会消耗非常长的时间(如果元素个数非常多),此时若使用二分查找算法那消耗的时间将大大降低。

现在我们使用二分查找算法来查找值为19的元素,如下图二分查找需要两个指针,一个指向元素列表的第一个元素叫做头指针,第二指向元素列表的最后一个元素的后一个Index(图中最后一个元素的Index为7,那么未指针就指向该元素的后一个Index,也就是图中的Index 8)叫尾指针。

要查找的范围就是头指针与尾指针之间的所有元素(注意:这边包含头指针所指向的元素但不包含尾指针指向的元素,其实尾指针并没有指向任何元素,只是指向了最后一个元素后一个Index)。

好了查找范围已经定下来了,接着我们开始查找吧。首先我们要寻找出查找范围的中间元素,可以通过头指针对应的Index值加上尾指针对应的Index值再除以2得出中间元素对应的Index。通过计算(0+8)/2=4可以得出中间元素的Index值为4,然后我们把该Index对应的元素值16与要查找的值19进行比较发现要查找的值大,不是要查找的值,所以我们将中间元素对应的Index值赋值给Head(因为示列元素列表是从小到大排列的)从而缩小查找范围,具体如下图所示。

接着我们在新的范围中继续查找中间元素,计算(4+8)/2=6(这边有个注意点,如果不能整除则只取结果的整数部门如7/2只取3)得出中间元素Index为6,我们通过比较该Index指向元素值23是否与要查找的值19相等,发现中间元素的值比19大所以我们把中间元素Index值赋值给尾指针,具体如下图。

然后我们再在上图新的范围中查找中间元素,通过计算(4+6)/2=5得出中间元素对应的Index值为5,接着比较该中间元素值19与要查找的值19是否相等,发现两值正好相等至此我们的查找结束。

3、 算法代码实现

上一个章节我们通过图解的方法已经了解了二分查找的实现原理,现在我们看看怎么用代码实现该算法吧,本节我们将通过python来演示,好了现在让我们来上代码:

1. #!/usr/bin/env/ python  
2. # -*- coding:utf-8 -*-  
3.   
4. import time  
5.   
6.   
7. def binary_search(search_list, search_value):  
8.     """ 
9.     :param search_list: 需要查找的数组列表 
10.     :param search_value:  需要查找的值 
11.     :return:  返回1表示已经查询到了, 返回-1表示没有查询到 
12.     """  
13.     head = 0 #设置head指针初始化的值  
14.     tail = len(search_list) #要查询的列表元素长度就是尾指针的索引值  
15.   
16.     while tail - head > 1: #当尾指针与头指针的差等于1时退出巡检,此时查找的数就是head指针指向的数  
17.         mid = (head + tail) // 2  #求出中间索引值  
18.         # 如果中间索引值对应元素值小于要找的数值,则将这个中间索引值加1赋值给head指针  
19.         # 这边加1是因为中间索引值对应的数小于查找的数值所以不应该把这个值包含在查找范围内  
20.         if search_list[mid] < search_value:   
21.             head = mid + 1  
22.         #找到则直接返回  
23.         elif search_list[mid] == search_value:  
24.             return 1  
25.         #否则将之间索引值赋值给tail指针  
26.         else:  
27.             tail = mid  
28.   
29.     else:  
30.         #如果在循环体内没有查询要对应的元素,则判断当前head对应元素值是否与查询的值相等  
31.         if search_list[head] == search_value:  
32.             return 1  
33.         else:  
34.             return -1  
35.   
36.   
37. if __name__ == "__main__":  
38.     search_list = [i for i in range(100000000)]  
39.     start = time.time()  
40.     print("查找的结果: ", binary_search(search_list, 9999999))  
41.     end = time.time()  
42.     print("查找耗时: ", end - start)  

代码执行结果,及耗时如下:

1. D:\env\python3_env\Scripts\python3.exe E:/it_code/sf_content.py  
2. 查找的结果:  1  
3. 查找耗时:  0.000997781753540039  
4.   
5. Process finished with exit code 0  
我们现在通过遍历的方法在相同的元素列表中查询相同的值看看耗费的时间,代码如下:
1. def _search(search_list, search_value):  
2.     for i in search_list:  
3.         if i == search_value:  
4.             return 1  
5.     return -1  
6.   
7.   
8. if __name__ == "__main__":  
9.     search_list = [i for i in range(100000000)]  
10.     start = time.time()  
11.     print("查找的结果: ", _search(search_list, 9999999))  
12.     end = time.time()  
13.     print("查找耗时: ", end - start) 

执行的结果如下:

1. D:\env\python3_env\Scripts\python3.exe E:/it_code/sf_content.py  
2. 查找的结果:  1  
3. 查找耗时:  0.27816343307495117  
4.   
5. Process finished with exit code 0  


相关文章:

宋朝的官服有什么特点?都有什么讲究?快来看看吧 01-06

茭白的做法,茭白怎么长期保存方法 01-06

蜂蜜的储存方法和适宜温度 ,是放冰箱里冷藏呢,还是放冰箱里冷冻? 01-06

微博视频怎么保存本地相册? 01-06

灭明朝的是谁?不是多尔衮不是吴三桂,而是这个人 01-05

明朝历代宰相列表 ,历16帝,仅有4位宰相,他们的结局如何? 01-05

明朝案件 :过路夫妻借宿店主女儿闺房,次日身首分离,扯出风月案 01-05

明朝历任内阁首辅 :万历皇帝老师张居正上榜还有那些呢 01-05

唐朝皇帝的龙袍几十年不换一次,难道不怕脏吗? 01-05

朱瞻基:明朝第五位皇帝 ,600年来,身上的谜团至今无解 01-05