二分查找快速理解

作为数据结构接触到的入门第一个算法,很多人对它不以为然,但是作为小白学习还是很有必要的,循序渐进,打开算法的大门

假如你要登录王者荣耀,当你这样做时,QQ或者微信必须核实你是否有其游戏的账户,因此在数据库中查找你的用户名和账号。如果你的用户名为king,腾讯可以从以A开头的部分开始查找,但更合乎逻辑的做法是从中间开始查找。

二分查找是一种算法,要求输入是一个有序的元素列表,我们结合程序的话,如果要查找的元素包含在列表中,则返回它的位置,否则返回NULL。

关于详细的原理,可以引入一个耳熟能详的小游戏——猜数字

将范围设定为1~100,你需要在最短次数内猜到这个数字,你每次猜测,我会说小了或者大了,直到猜中。

假如你从1开始依次往上猜,如果我想的数字是99,你岂不是需要猜99次?显然令人啼笑皆非

你可能会说,我怎么可能这么傻,那么,我们就引申出了一种更佳的猜法:

从50开始,每次都从中间值开始猜,如果我说小了,那么你下一次的猜测就从75开始,反之就从25开始。无论如何,余下的数字都排除了一半,你猜的一直是中间的数字,所以每次都能排除一半。

最终的结果就是,无论我想的是什么数字,你在7次之内都能找到,因为每次都排除掉一半。

而且,元素越多的情况下,二分查找相较于简单查找的优势只会更大

有数学基础的你可能已经发现了,对于包含n个元素的列表,二分查找最多需要log2^n次,简单查找最多需要n次!

如果你不清楚对数的概念,可以先去了解一下,对于后续数据结构的学习大有裨益。

二分查找快速理解_第1张图片

二分查找快速理解_第2张图片

接下来结合python代码对二分查找进行简单实现

这里的示例使用了数组,不熟悉数组的可以先去了解一下相关概念,后续数据结构会经常出现

简单说就是:将一系列元素存储在一系列相邻的盒子中,这些盒子从0开始编号,因此第一个盒子的位置为0,第二个位置为1,第三个就是2……以此类推

# 定义二分查找函数,接收一个有序列表和待查找元素
def binary_search(list, item):
    # 初始化查找范围的最低索引
    low = 0
    # 初始化查找范围的最高索引(列表长度减1)
    high = len(list) - 1

    # 当查找范围存在时循环(低索引不大于高索引)
    while low <= high:
        # 计算中间索引:使用整数除法避免浮点数
        mid = (low + high) // 2  # 修改1:使用//进行整数除法
        # 获取中间索引对应的值
        guess = list[mid]

        # 如果中间值等于目标值
        if guess == item:
            # 返回目标值的索引
            return mid
        # 如果中间值大于目标值
        if guess > item:
            # 将查找范围上限设为中间索引前一位(排除右半部分)
            high = mid - 1
        # 如果中间值小于目标值
        else:
            # 将查找范围下限设为中间索引后一位(排除左半部分)
            low = mid + 1
    # 未找到目标值,返回None(已移到循环外) # 修改2:将return None移到while循环外
    return None  

# 创建测试用的有序列表
my_list = [1, 3, 5, 7, 9]

# 查找元素3并打印结果(预期返回索引1) # 修改3:使用print()函数
print(binary_search(my_list, 3))  
# 查找不存在的元素-1并打印结果(预期返回None) # 修改4:使用print()函数
print(binary_search(my_list, -1))  

以查找数字3为例,查找过程如下:

初始范围:[1,3,5,7,9] (low=0, high=4)
2. 中间索引:2 → 值5 > 3 → 调整high=1
3. 新范围:[1,3] (low=0, high=1)
4. 中间索引:0 → 值1 < 3 → 调整low=1
5. 中间索引:1 → 值3 == 3 → 返回索引1

你可能感兴趣的:(二分查找快速理解)