查找算法的python实现(一:线性查找、二分查找及其改进)

今天学查找算法,先写线性查找、二分查找及两种改进(插值查找和斐波那契查找)。树查找、散列查找等以后再补。

def linear_search(nums: list, value) -> int:
    """
    线性查找
    :param nums:被查找序列
    :param value:目标值
    :return:目标值在被查找序列中的索引,查不到时为-1
    """
    for i, num in enumerate(nums):
        if num == value: return i
    return -1


def binary_search(nums: list, value) -> int:
    """
    二分查找
    :param nums:被查找序列,要求已排好序
    :param value:目标值
    :return:目标值在被查找序列中的索引,查不到时为-1
    """
    start, end = 0, len(nums) - 1  # 初始化始末索引
    if value < nums[start] or value > nums[end]: return -1  # 如果目标值越界,直接返回-1
    while start <= end:
        mid_index = (start + end) // 2  # 计算中间索引
        if value == nums[mid_index]: return mid_index  # 如果中间值等于目标值,返回中间索引
        elif value < nums[mid_index]: end = mid_index - 1  # 如果目标值小于中间值,修改结束索引为中间索引的前一个位置
        else: start = mid_index + 1  # 如果目标值大于中间值,修改开始索引为中间索引的后一个位置
    return -1


def interpolation_search(nums: list, value) -> int:
    """
    插值查找
    :param nums:被查找序列,要求已排好序
    :param value:目标值
    :return:目标值在被查找序列中的索引,查不到时为-1
    """
    start, end = 0, len(nums) - 1
    if value < nums[start] or value > nums[end]: return -1
    # 增加nums[start] != nums[end]条件防止分母为零
    while start <= end and nums[start] != nums[end]:
        mid_index = start + int(((value - nums[start]) / (nums[end] - nums[start])) * (end - start))  # 计算中间索引,基于值的比例进行插值计算
        if value == nums[mid_index]: return mid_index
        elif value < nums[mid_index]:
            end = mid_index - 1
            if value > nums[end]: break  # 避免在近似值内循环
        else:
            start = mid_index + 1
            if value < nums[start]: break  # 避免在近似值内循环
    if nums[start] == nums[end] == value: return start  # 若因开始和结束索引的值相等退出,检查其是否为目标值
    return -1


def fibonacci_search(nums: list, value) -> int:
    """
    斐波那契查找
    ### 改进建议
    1. **增强逻辑严密性**:虽然使用黄金分割比的近似值来近似斐波那契查找可能在很多情况下有效,但在特定数据分布或特定情境下,可能无法达到与真正的斐波那契查找相同的效率。因此,可以考虑实现标准的斐波那契查找算法,以更准确地反映其原始意图和潜在的性能优势。
    :param nums:被查找序列,要求已排好序
    :param value:目标值
    :return:目标值在被查找序列中的索引,查不到时为-1
    """
    start, end = 0, len(nums) - 1
    if value < nums[start] or value > nums[end]: return -1
    while start <= end:
        mid_index = start + int(((5 ** 0.5 - 1) / 2) * (end - start))  # 使用斐波那契数列太麻烦了,这里直接用黄金分割点的近似值,效果也差不多。
        if value == nums[mid_index]: return mid_index
        elif value < nums[mid_index]: end = mid_index - 1
        else: start = mid_index + 1
    return -1


if __name__ == '__main__':
    from random import choices
    nums = choices(range(100), k=10)
    sorted_nums = sorted(nums)
    print(f'nums:{nums}\nsorted_nums:{sorted_nums}')
    print(f'Search:{nums[-1]},result:\n'
          f'    linear_search:{linear_search(nums, nums[-1])}\n'
          f'    binary_search:{binary_search(sorted_nums, nums[-1])}\n'
          f'    interpolation_search:{interpolation_search(sorted_nums, nums[-1])}\n'
          f'    fibonacci_search:{fibonacci_search(sorted_nums, nums[-1])}')
    print(f'Search:{100},result:\n'
          f'    linear_search:{linear_search(nums, 100)}\n'
          f'    binary_search:{binary_search(sorted_nums, 100)}\n'
          f'    interpolation_search:{interpolation_search(sorted_nums, 100)}\n'
          f'    fibonacci_search:{fibonacci_search(sorted_nums, 100)}')

输出:

nums:[13, 35, 11, 2, 96, 37, 5, 48, 48, 45]
sorted_nums:[2, 5, 11, 13, 35, 37, 45, 48, 48, 96]
Search:45,result:
    linear_search:9
    binary_search:6
    interpolation_search:6
    fibonacci_search:6
Search:100,result:
    linear_search:-1
    binary_search:-1
    interpolation_search:-1
    fibonacci_search:-1

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值