『算法』——静态查找——线性表查找——二分查找(折半查找/对分查找)

引言

  • 二分查找是顺序表或线性链表表示的静态查找表
  • 表内元素有序

1、定义

\quad \quad 二分查找针对的是一个有序的数据集合,每次通过跟区间中间的元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间缩小为0。

2、思想

\quad \quad 假设表中元素是有序的,将表的中间位置的关键字与所需的关键字比较,相等则成功,否则分为前后两个子表,若所需的值大于中间元素,则在后半部分查找,否则在前半部分查找。不断重复这个过程,直到查找成功。否则查找失败。需要两个移动指针p,r,分别指向列表的上界与下界。

3、算法

伪代码

在这里插入图片描述

python:

#非递归实现
import numpy as np
def binary_search(A,x):
    A=np.sort(A)#先将A排序
    n=len(A)
    #搜索区间范围:左闭右闭[left,right]
    p=0#p:头指针
    r=n-1#r:尾指针
    while p<=r:
        q=(p+r)//2#//符号:商取整
        #或q=p+(r-p)//2,防止溢出,最好使用这种取中值的方法
        if A[q]==x:
            return q
        elif A[q]>x:
            r=q-1
        else:
            p=q+1
    return print("NOT FOUND")

另一种非递归模板:

import numpy as np
def binary_search(A,x):
    A=np.sort(A)#先将A排序
    n=len(A)
    #区间范围:左闭右开[left,right)
    p=0#p:头指针
    r=n#r:尾指针
    while p<r:
        q=(p+r)//2#//符号:商取整
        #或q=p+(r-p)//2,防止溢出,最好使用这种取中值的方法
        if A[q]==x:
            return q
        elif A[q]>x:
            r=q
        else:
            p=q+1
    return print("NOT FOUND")

#递归实现(p,r)一般刚开始是(0,len(A)-1)也就是列表中第一个与最后一个位置
def recursive_binary_search(A,p,r,x):
    A=np.sort(A)#先将A排序
    if p>r:
        return print("NOT FOUND")
    else:
        q=(p+r)//2
        if A[q]==x:
            return q
        elif A[q]>x:
            return recursive_binary_search(A,p,q-1,x)
        else:
            return recursive_binary_search(A,q+1,r,x)
   

中位数的计算方法:

1、mid = (left + right) / 2; 是初级写法,是有 bug 的:有可能会溢出。

2、 mid = left + (right - left) / 2; 是正确的写法,考虑到了整型溢出的风险;

3、mid = (low + high) >> 1; 右移运算符>>,运算结果正好能对应一个整数的二分之一值,这就正好能代替数学上的除2运算,但是比除2运算要快。

4、查找性能(ASL)

在这里插入图片描述

【时间复杂度】: O ( l o g 2 n ) O(log_2n) O(log2n)
【空间复杂度】:

  • 递归实现: O ( l o g 2 n ) O(log_2n) O(log2n)
  • 非递实现: O ( 1 ) O(1) O(1)

5、特点

优点:比较次数少,时间性能相对于顺序查找要好,效率要快

缺点:要求待查表为有序表,且限于顺序存储结构(对线性链表无效)。

局限性:

1.二分查找依赖的是顺序表结构,即数组。
2.二分查找针对的是有序数据,因此只能用在插入、删除操作不频繁,一次排序多次查找的场景中。
3.数据量太小不适合二分查找,与直接遍历相比效率提升不明显。但有一个例外,就是数据之间的比较操作非常费时,比如数组中存储的都是长度超过300的字符串,那这是还是尽量减少比较操作使用二分查找吧。
4.数据量太大也不是适合用二分查找,因为数组需要连续的空间,若数据量太大,往往找不到存储如此大规模数据的连续内存空间。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值