Python实现二分法搜索

您所在的位置:网站首页 python3二维数组中查找单词 Python实现二分法搜索

Python实现二分法搜索

#Python实现二分法搜索| 来源: 网络整理| 查看: 265

Python实现二分法搜索

二分法是一种效率比较高的搜索方法,时间复杂度为 O(log2n) 。

假设有一个1~100之间的数字,你来猜这个数是多少,每猜一次可以得到三种回答:正确、大了或小了。如何保证用最少的次数猜对?很多人会想到先猜50,如果猜大了,说明答案比50小,然后猜25...用这种方法,每次都可以将数字的范围缩小一半,对于1~100之间的任何数,最多都只需要7次就能找到答案。

这种每次将搜索范围缩小一半的方法,就是二分法搜索的思想。本文使用 Python 来实现二分法搜索。

一、Python 二分法搜索递归实现

在实现代码前,先分析二分法的前提条件:

1. 上面的例子在1~100中查找一个数字,每次都要判断是大了还是小了,这里隐含了一个条件,即1~100是升序排列的。对于二分法,数据列表必须是有序的,一般是升序,降序也可以。

2. 跳出1~100的范围,对于任何的数据集合,都可以使用二分法来搜索其中的某个数。

现在来看一下二分法搜索的具体过程。如在 [50, 77, 55, 29, 10, 30, 66, 18, 80, 51] 中搜索 77 。

1. 对列表排序。通常的数据很少是排好序的,要使用二分法,就要先对数据列表进行排序。

2. 取一半位置的数据。对于一个数据集合,数据量可能是奇数,也可能是偶数,但不管奇数偶数,都取2的整除。

所以,这里先找到一半位置的50。

3. 判断中间位置的数字与目标数字的大小,缩小搜索范围,然后重复第2步。

4. 继续重复2和3,直到找到目标数据。

根据搜索的过程,来实现代码。

# coding=utf-8 class BinarySearch(object): def binary_search(self, array, data): """二分查找法递归实现""" if len(array) == 0: return False array.sort() mid_index = len(array) // 2 if array[mid_index] == data: return True return self.binary_search(array[mid_index + 1:], data) if data > array[mid_index] else \ self.binary_search(array[:mid_index], data)

binary_search(array, data):在数据列表 array 中搜索数据 data 。每次递归搜索,数据列表的长度都会缩小“一半”,当找到目标数据或数据列表的长度为0时,递归结束。

if __name__ == '__main__': array = [50, 77, 55, 29, 10, 30, 66, 18, 80, 51] search = BinarySearch() print('搜索结果:', search.binary_search(array, 77)) print('搜索结果:', search.binary_search(array, 777))

运行结果:

搜索结果: True 搜索结果: False

二、Python 二分法搜索非递归实现

二分法搜索也可以使用非递归的方法实现,还是以在  [50, 77, 55, 29, 10, 30, 66, 18, 80, 51] 中搜索 77 为例。

1. 对列表排序。

2. 取一半位置的数据。这里策略不变,还是取中间位置的数据。但因为是非递归方式,只能通过循环的方式来实现多次二分,如果第一次没有找到目标数据,第二次取一半位置的索引时,就需要根据第一次的判断结果来计算中间索引。因此需要设置两个游标来记录每次二分的开始索引 start 和结束索引 end,如果没有找到目标数据,就修改开始索引或结束索引的值,用于下一次循环中计算中间索引。

3. 根据第一次循环的判断结果,修改开始索引的值,重新计算中间索引和取中间位置的数据。

4. 重复循环直到找到目标数据。当 start 的值等于 end 的值时,范围已经缩小到只剩一个数据,如果继续循环,start 大于 end,说明找不到目标数据,循环结束。

根据这个过程,来实现代码。

def binary_search_normal(self, array, data): """二分查找法非递归实现""" array.sort() start, end = 0, len(array)-1 while start array[mid_index]: start = mid_index + 1 else: end = mid_index - 1 return False

binary_search_normal(array, data):在数据列表 array 中搜索数据 data 的非递归实现。每次循环,都会根据判断结果修改 start 或 end 的值,下一次循环中根据新的 start 和 end 值计算新的 min_index,直到找到目标数据或找完整个数据列表(start>end),循环结束。

print('搜索结果:', search.binary_search_normal(array, 77)) print('搜索结果:', search.binary_search_normal(array, 777))

运行结果:

搜索结果: True 搜索结果: False

三、二分法搜索与二叉搜索树的关系

关于Python实现二叉搜索树,可以参考:https://blog.csdn.net/weixin_43790276/article/details/105753543。

如果将上面的数据 [50, 77, 55, 29, 10, 30, 66, 18, 80, 51]  添加到二叉搜索树中,得到的二叉搜索树结构如下。

根据二叉搜索树的特性,在向二叉搜索树中插入数据时,就已经先判断了插入数据与根节点数据的大小,小的插入到左子树中,大的插入到右子树中,所以在二叉搜索树中搜索数据时,可以比较数据与根节点的数据大小,递归判断是在左子树还是在右子树中搜索。每一次递归,都会将范围缩小到左子树或右子树,直到找到目标数据。这种搜索方式与二分法搜索的思路非常相似。

二叉搜索树可以理解为二分法实现的一种数据结构,但并不完全是,因为二叉搜索树只是满足了二分法的思想,与二分法是有区别的。

二分法每次都肯定可以将数据范围缩小“一半”,因为数据长度可能是奇数个或偶数个,二分后的两个数据集合的数量要么相等要么相差1。而在二叉搜索树中,左右子树的节点数量取决于添加的顺序,并不一定满足数量相等或最多相差一个。

要满足二叉搜索树的特性,还要控制左子树和右子树的节点数量差异,就需要对二叉搜索树的“平衡”进行控制,在数据结构中,按这种思路实现的二叉树叫红黑树,后面的文章继续研究。

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3