【11】数据结构之基于线性表的查找算法

平均查找长度ASL(Average Search Length)

  • 定义:为确定元素在列表中的位置,需要和给定值进行比较的关键字个数的期望值,称之为查找算法成功时的平均查找长度.

ASL = P 1 C 1 + P 2 C 2 + ⋯ + P n C n = ∑ i = 1 n P i C i \text{ASL} = P_1C_1 + P_2C_2 + \cdots + P_nC_n = \sum_{i=1}^{n} P_iC_i ASL=P1C1+P2C2++PnCn=i=1nPiCi

其中,P为第i个元素的概率,C为找到列表中第i个元素时,已经进行过的关键字比较次数.

顺序表查找法

  • 简单粗暴的查找方法,从头开始扫描,直到查找到或扫描结束.
# 1.顺序表查找法
class SeqList:
    def __init__(self, items):
        # 顺序表
        self.items = items

    def seqSearch(self, key):
        # 顺序表查找法
        index = -1
        for i in range(len(self.items)):
            if self.items[i] == key:
                index = i + 1
        return index


if __name__ == '__main__':

    print('PyCharm')
    # 1.顺序表调试
    nums = [15, 22, 83, 54, 6, 65, 96, 72, 38, 46]
    sqlist = SeqList(nums)
    print(sqlist.seqSearch(72))
  • 运行结果

在这里插入图片描述

  • 顺序表查找法的ASL:
    • 假设长度为n,
    • 假设最后一个元素为查找目标,需比较n次,
    • 倒数第二个元素为查找目标,需比较n-1次,
    • 依此类推,
    • 第一个元素为查找目标,需比较1次.
    • 设每个元素为目标元素的概率一致,则概率值为1/n.

ASL = 1 × 1 n + 2 × 1 n + ⋯ + n × 1 n = ( 1 + 2 + ⋯ + n ) × 1 n = n + 1 2 \text{ASL} = 1 \times \frac{1}{n} + 2 \times \frac{1}{n} + \cdots + n \times \frac{1}{n} = \left(1 + 2 + \cdots + n\right) \times \frac{1}{n} = \frac{n+1}{2} ASL=1×n1+2×n1++n×n1=(1+2++n)×n1=2n+1

折半查找法

  • 前提条件:

    • 1.采用顺序存储结构
    • 2.必须按关键字大小有序排列
  • 基本思想:

    • 关键字先与中间元素比较:

      • 若相等,则查找成功
      • 若关键字大,则与后一子表的中间元素比较大小,
      • 若关键字小,则与前一子表的中间元素比较大小,
    • 重复查找,直到查找成功,或比较结束,未查找到.

  • 查找失败情况
    在这里插入图片描述

  • 查找成功情况
    在这里插入图片描述

# 2.折半查找法
class SeqList:
    def __init__(self, items):
        # 有序的顺序表
        self.items = items

    def binarySearch(self, key):
        # 折半查找法
        index = -1
        low = 0
        high = len(self.items) - 1
        while high >= low:
            mid = (low + high) // 2
            if self.items[mid] == key:
                index = mid + 1
                break
            elif self.items[mid] > key:
                high = mid - 1
            else:
                low = mid + 1
        return index



if __name__ == '__main__':

    print('PyCharm')
    # 2.折半查找调试
    nums = [6, 12, 15, 18, 22, 25, 28, 35, 46, 58, 60]
    sqlist = SeqList(nums)
    num = 12
    index = sqlist.binarySearch(num)
    if index == -1:
        print(f"{num}{nums}中未找到")
    else:
        print(f"{num}{nums}中的位置为{index}")

    num = 50
    index = sqlist.binarySearch(num)
    if index == -1:
        print(f"{num}{nums}中未找到")
    else:
        print(f"{num}{nums}中的位置为{index}")
  • 运行结果

在这里插入图片描述

  • 折半查找法的ASL:

ASL = ∑ i = 1 n P i C i = 1 n ∑ j = 1 n j × 2 j − 1 = n + 1 n log ⁡ 2 ( n + 1 ) − 1 ≈ log ⁡ 2 ( n + 1 ) − 1 \text{ASL} = \sum_{i=1}^{n} P_i C_i = \frac{1}{n} \sum_{j=1}^{n} j \times 2^{j-1} = \frac{n+1}{n} \log_2(n+1) - 1 \approx \log_2(n+1) - 1 ASL=i=1nPiCi=n1j=1nj×2j1=nn+1log2(n+1)1log2(n+1)1

  • 优点:

    • 比较次数少,查找速度快,平均性能好.
  • 缺点:

    • 要求待查表为有序表且插入/删除困难.

索引顺序查找法

  • 分块查找法,介于顺序查找法和折半查找法之间的一种查找方法.

  • 关键:建立索引表

  • 前提条件:要求将列表组织称索引顺序结构

  • 索引表示意图

在这里插入图片描述

# 3.索引顺序查找表
class Block:
    def __init__(self, key, low, high):
        self.key = key
        self.low = low
        self.high = high + 1

class SeqList:
    def __init__(self, blocks, items):
        self.blocks = blocks
        self.items = items

    def seqSearch(self, cur, key):
        # 索引顺序查找
        index = -1
        low = self.blocks[cur].low
        high = self.blocks[cur].high
        for i in range(low, high):
            if self.items[i] == key:
                index = i + 1
        return index

    def blockSearch(self, key):
        low = 0
        high = len(self.blocks) - 1
        mid = 0
        while low <= high:
            mid = (low+high)//2
            if mid == 0 or mid == len(self.blocks) -1:
                break
            elif key < self.blocks[mid].key and key > self.blocks[mid-1].key:
                break
            elif key > self.blocks[mid].key:
                low = mid + 1
            elif key < self.blocks[mid].key:
                high = mid - 1
        index = self.seqSearch(mid, key)
        return index


if __name__ == '__main__':

    print('PyCharm')
    # 3.索引表查找调试
    nums = [18, 14, 12, 25, 8, 28, 32, 45, 36, 58, 60, 88, 71]
    blocks = [Block(25, 0, 4),Block(58, 5, 9),Block(88, 10, 12)]
    sqlist = SeqList(blocks, nums)
    num = 36
    print(f"{num}{nums}中的位置为{sqlist.blockSearch(num)}")
  • 运行结果

在这里插入图片描述

  • 36查找的过程:

    • 将36与索引表中最大关键字25与58比较,介于他们之间,则表明36在第二块索引表中.
    • 从第二块索引表的起始地址开始扫描,最后找到36所在位置.
  • 索引表查找的ASL:

    • 其中,n为数组数量,s是每块含有元素的个数.

ASL = 1 2 ( n s + s ) + 1 \text{ASL} = \frac{1}{2} \left( \frac{n}{s} + s \right) + 1 ASL=21(sn+s)+1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_x_w

你的肯定是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值