查找算法——线性查找、二分查找

列表查找:从列表中查找指定元素。

列表查找的两种方法备注

顺序查找

(也叫线性查找)

两种方式:

(1)自己写段代码。

(2)用列表内置函数index( )

列表有序无序都可以
二分查找自己写段代码

列表必须有序,

如果无序得先排序。

一、顺序查找(线性查找)—— 时间复杂度:O(n)

        也叫线性查找,linear search,从列表的第一个元素开始,顺序进行搜索,也就是,一个个找下去,直到找到目标元素,或搜索到列表最后一个元素为止。

# 法1 最容易想到的
def linear_search(li, val):
    for i in range(len(li)):
        if li[i] == val:
            return i
    else:
        return None


result = linear_search([1, 2, 3, 4, 5], 5)  # 找5在不在列表里
print(result)

# 结果:
4


# 找9
result = linear_search([1, 2, 3, 4, 5], 9)
print(result)

# 结果:
None
# 法2 用enumerate()函数进行枚举
def linear_search(li, value):
    for index, v in enumerate(li):
        if v == value:
            return index
    else:
        return None


result = linear_search([1, 2, 3, 4, 5], 5) # 找5
print(result)

# 结果:
4

# 找9
result = linear_search([1, 2, 3, 4, 5], 9)
print(result)

# 结果:
None

二、二分查找(折半查找)—— 时间复杂度:O(logn)

        又叫折半查找,binary search,从有序列表的初始候选区li[0:n]开始,通过将目标元素与候选区的中间值进行比较,可以使候选区减少一半。

也就是说,首先列表要有序,然后每次拿候选区的中间值与目标元素进行比较,如果它比中间值大,则候选区变成,中间值的右边那部分,如果比中间值小,则候选区变成中间值左边的那部分。即:每查找一次,候选区就会减少一半。

代码:

def binary_search(li, target):
    left = 0
    right = len(li) - 1

    while left <= right:  # 保证候选区有值
        mid = (left + right) // 2
        if li[mid] == target:
            return mid
        elif li[mid] > target:  # 目标元素在mid左边
            right = mid - 1
        else:
            left = mid + 1  # 目标元素在mid右边
    else:
        return None


result = binary_search([1, 2, 3, 4, 5], 5)
print(result)

# 结果:
4

# 找9
result = binary_search([1, 2, 3, 4, 5], 9)
print(result)
# 结果:
None

!!!注意避坑:!!!!

上面代码中,注意:mid = (left + right) // 2  这行代码的位置
因为mid会随着left、 right值的变化而变化,所以mid表达式要放在while循环里面,否则代码就会进入死循环。

效果演示:

同理:找9,由第三步可知,此时,left=right,说明候选区已经没有数了,所以说明9不在里面。

三、线性查找 VS 二分查找

        由时间复杂度可知,二分查找速度快,但前提是,列表必须有序,否则得先对列表进行排序。而线性查找无所谓,有序无序都可以,查找的过程就是拿要查找的值与列表中的值一个个对比,缺点是速度慢。

        需要注意的是,如果列表无序,先对列表升序排序完,再用二分查找话,这样的可能就没有线性查找快,因为排序费时间,排序的时间复杂度 > O(n),但是如果说,排序后要查找很多次,那还是二分查找快,如果只查找一两次,那就是线性查找快。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值