数据结构与算法 | 二分查找

1 前言

关于二分查找,首先来看一个段子,见下图:
在这里插入图片描述
有点意思,虽然是个段子,但是大妈查找有问题书的方式其实就是今天我们要说的二分查找!也叫折半查找!下面就跟随小编的角度来具体看看什么叫二分查找吧!

2 什么叫二分查找?

  • 搜索是在一个项目集合中找到一个特定项目的算法过程。
  • 搜索通常的答案是真的或假的,因为该项目是否存在。 搜索的几种常见方法:
    • 顺序查找
    • 二分法查找
    • 二叉树查找
    • 哈希查找

关于顺序查找就比较简单了,就是从头开始,一个元素一个元素的遍历!效率比较低!

下面主要讲述二分查找!

  • 二分查找又称折半查找。优缺点见下:

    • 优点:比较次数少,查找速度快,平均性能好;
    • 缺点:要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表
  • 二分查找的实现过程如下:

    • 首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较
    • 如果两者相等,则查找成功;
    • 否则利用中间位置记录将表分成前、后两个子表
    • 如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。
    • 重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
  • 图解:要查找的元素为4
    在这里插入图片描述

3 代码实现

3.1 递归版本

递归思路:

  • 首先要对序列进行排序吗?不需要,必须是有序的!
  • 排序ok之后 开始考虑二分查找 所以是不是还需要再传入一个参数 就是一个具体的数值?判断这个值在不在list当中?yes!
  • 首先对序列进行对半砍,然后判断中值和传入的value进行比较!大于则在右边查找 小于在左边查找!递归调用函数,参数变为新的list
  • 上述循环加一个终止条件 也就是当list元素只有一个的时候!

递归版本:

def binary_search(alist, value):
    '''二分查找'''

    n = len(alist)
    mid = (0+n) // 2
    
    while n > 0: # 递归的终止条件 即大于等于一个元素的时候
        if alist[mid] == value:
            return True
        elif value < alist[mid]:
            # 左半部分查找
            return binary_search(alist[:mid],value)
        else:
            # 右半部分查找
            return binary_search(alist[mid+1:], value)
    return False
testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
print(binary_search(testlist, 3))
print(binary_search(testlist, 13))
False
True
li = [17, 20, 26, 31, 44, 54, 55, 77, 93]
print(binary_search(li, 55))
print(binary_search(li, 100))
True
False

3.2 非递归版本

非递归思路:

  • 不是将切片后的list传入,而是每次改变位置即可!
  • 原理和上面递归的类似,就是二分查找,小于中间值则在左边查,大于右边查,只是每次修改起始和终止的位置
def binary_search(alist, value):
    '''二分查找 非递归版本'''
    
    n = len(alist)
    first = 0
    last = n-1
    
    while first <= last:
        # 必须在循环体内部计算 因为每次查找要么first要么last会发生变化
        mid = (first + last) // 2
        
        if alist[mid] == value:
            return True
        elif value < alist[mid]:
            # 修改查找范围
            last = mid - 1
        else:
            first = mid + 1
    return False
testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
print(binary_search(testlist, 3))
print(binary_search(testlist, 13))
False
True
li = [17, 20, 26, 31, 44, 54, 55, 77, 93]
print(binary_search(li, 55))
print(binary_search(li, 100))
True
False

4 时间复杂度

二分查找(折半查找)时间复杂度:

  • 最优就是常数 O ( 1 ) O(1) O(1),因为一查就查到了
  • 最差对数复杂度 O ( l o g n ) O(logn) O(logn)

普通查找时间复杂度:

  • 最优就是常数 O ( 1 ) O(1) O(1),因为一查就查到了
  • 最差是线性复杂度 O ( n ) O(n) O(n)

5 知识点补充

  • " / " 表示浮点数除法,返回浮点结果;
  • " // " 表示整数除法,返回不大于结果的一个最大的整数
6 / 4
1.5
6 // 4
1

参考

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值