文章目录

    datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_概率论


    顺序查找

    一般线(无序)性表的顺序查找

    • 对于含有n个元素的线性表,给定值key和表中的第i个元素相等(查找成功)的定位需要进行:datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_线性表_02次关键字比较
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_概率论_03
    • 设每个元素的查找概率相等,
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_概率论_04
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_算法_05

    有序线性表的顺序查找

    • 有序线性表和无序线性表的顺序查找的差别体现在查找失败是需要比较关键字的次数
    • 查找成功的平均查找长度和无序顺序表是一致的(datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_顺序查找_06)
    • 假设有序查找表序列为datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_线性表_07
    • 那么查找失败的元素可能来自于(对应于)datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_折半查找_08
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_算法_09
    • 那么共有n+1个区间
    • 假设来自这n+1个区间的元素的概率一致,datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_概率论_10
    • 第一个区间中的元素(记为datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_线性表_11判断出查找失败需要比较的次数为1次
    • 类似的定义第类个元素datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_折半查找_12判断出查找失败需要比较2次
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_概率论_13需要比较n次
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_顺序查找_14比较特殊,因为判断和最后一个元素比较完后,只要不等于datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_顺序查找_15那么就可以判断查找失败
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_算法_16
    • 所以有序线性表的顺序查找的失败凭据查找长度
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_概率论_17

    平均查找长度

    • 在实际应用的大多数情况下,查找成功的可能性比不成功的可能性大得多,
    • 特别是在表中记录数n很大时,查找不成功的概率可以忽略不计。
    • 当查找不成功的情形不能忽视时,查找算法的平均查找长度应是
    • 查找成功时的平均查找长度与查找不成功时的平均查找长度之和
    • 对于顺序查找,不论给定值key为何值,查找不成功时和给定值进行比较的关键字个数均为1+n
    • 假设查找成功与不成功的可能性相同,对每个记录的查找概率也相等,则
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_算法_18,此时顺序查找的平均查找长度为

    折半查找(二分查找)内含&性能分析

    二分查找算法

    ##
    ol=list(range(10))#order list
    # import numpy as np
    # 你需要的不是ndarray,而是array
    # ol=2*np.array(ol)+3
    ##
    print(ol)
    ##
    def binarySearch(ol,k):
        """ 二分查找(参数有序顺序表) """
        l=0
        r=len(ol)-1
        while(l<=r):
            mid=(l+r)//2
            print('indexes:[%d,%d],mid:%d' %(l,r, mid))#log
            if(ol[mid]==ol[k]):
                return mid
            if(k<mid):
                r=mid-1
            if(mid<k):
                l=mid+1
        return -1
    print(binarySearch(ol, 7))

    二叉排序树

    • 左子树上的所有的结点的关键字均小于根结点的关键字
    • 右子树上的所有结点的关键字均大于根结点的关键字
    • 左子树和右子树根子又是一棵二叉排序树
    • 如果给二叉排序树中的顶点按照从小到大编号,那么编号顺序和二叉树的中序遍历下的访问顺序是一样的
    • 二叉排序树未必是一棵平衡树,反之才成立
    • 在最坏的(最不平衡)的情况下,二叉排序树是一棵单枝树,性能和链表一样都是O(n)
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_概率论_19

    判定树

    • 有序表的顺序查找中,折半查找的过程可以用二叉判定树来描述
    • 判定树是一棵平衡树
    • 但不是所有的平衡树都可能称为判定树
    • 也是一棵二叉排序序树
    • 构建一个关键字比较序列有两种偏好:每个点都应该坚持同一种方式计算,否则不合法
    • 折半中点datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_折半查找_20
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_顺序查找_21
    判定树相关问题
    • 对于给定一棵平衡树,如果我按照中序遍历的顺序编号遍历的的点
    • 然后基于这些遍历的点推断各个节点的序号是采用datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_顺序查找_22
    • 如果该平衡树的中序遍历序号(标记在节点旁)全部都是通过datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_折半查找_23
    • 否则如果混合出现两种偏好,那么就不是一棵判定树
    • 判定树经常被用来结局给定序列(长度),求解关键字比较次数的问题/平均查找长度
    判断给定的序列能否构成折半查找关键字比较序列
    • 可以用给定的序列(元素值)尝试构建二叉排序树,如果无法构建,那么它就不是折半查找关键字比较序列

    通用的计算折半查找的定义法

    • 为了简单起见,先仅讨论比较整齐的满二叉树的情况
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_折半查找_24
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_顺序查找_25
    • 根结点是有序顺序表的中间元素
    • 左子树(的根结点)<根结点<右子树(的根结点)
    • 根据要查找的元素的不同,在所有查找成功的情况中
    • 在第一层查找成功的元素只需要比较1次
    • 在第二层查找成功则共需要比较2次(每层一次,共计2次)
    • 在第h层查找成功,则需要比较h次(每层1次,共计h次)
    • 如果所有元素查找概率相等,那么第一层有一个元素,共有1*1次
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_算法_26
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_概率论_27
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_线性表_28
    • 又假设所有元的查找概率相同,(即,所有层的所有元素之间的被查找概率一致)
    • 可以假设要对判定树每个元素构成的待查找序列进行分别查找
    • 总的查找次数为:datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_线性表_29
    • 利用错位相减法,计算上面的求和式:
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_算法_30

    满二叉判定树的查找成功的平均查找长度

    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_概率论_31

    求和式的一些性质

    • 联系求和式datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_算法_32以及它的展开datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_线性表_33是求和号的一些性质的源泉
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_线性表_34
    求和号错位相减中的应用
    • 具体参考
    • math_等差数列/等比数列求和推导&等幂和差推导/两个n次方数之差与等价无穷小实例/求和符号的性质和应用_xuchaoxin1375的博客-博客

    datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_概率论_35

    datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_线性表_36折半查找的成功查找的平均长度

    datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_顺序查找_37

    datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_算法_38

    • 当n比较大的时候,datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_线性表_39
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_顺序查找_40
    • 对于有n个结点判定树(高度可以类似完全二叉树的方法计算,都是datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_顺序查找_41)
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_顺序查找_42
    • 上面的datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_折半查找_43并不是通用的(只有当判定树为满二叉树才可以用)
    • 一般还是按照定义,来求解ASL
    • 一般的判定树除了最后一层不一定满,其余层都是满的
    • 而且是平均情况

    极端情况

    • 如果是规定了查找表长度,往往要计算最坏情况
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_顺序查找_44就能够判定查找失败或者成功(结合一般的判定树高度)
    • 最好情况则是datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_算法_45次比较
    • 例如n=16时,$判断出一个元素查找失败至少要37/12;最多要:49/13

    分块查找

    • 结合了顺序查找和折半查找的优点
    • 分块查找,块内无序
    • 块之间有序
    • 而且第一个块的所有元素小于第二个块的所有元素
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_顺序查找_46
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_算法_47
    • 每块内最大元素或者最小元素的数据组成了索引块

    索引表

    • 索引表中的每个元素各含有各块的最大(或最小)关键字和各块中的第一个元素地址
    • 索引表按照关键字有序排列

    查找过程

    • 确定索引表中待查找的记录所在的索引块
    • 这一部分可采用折半查找或者顺序查找
    • 在块内进一步查找
    • 一般块内是无序的,则采用顺序查找
    • 但如果是有序表的强化分块,那么还可以选用折半查找

    性能分析

    • 分块查找的平均查找长度为:
    • 索引查找和块内查找的平均查找长度之和
    • 设索引查找和块内查找的平均查找长度分别为datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_算法_48
    • 其他极端策略结合折中案例
    • 在计算机组成原理中,cache和内存的映射策略中,直接映射和全相联映射折中出了组相联映射
    索引表采用顺序查找的性能
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_折半查找_49
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_算法_50
    • 有基本不等式可得,datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_折半查找_51
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_线性表_52
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_线性表_53
    索引表采用折半查找的性能
    • datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_顺序查找_54

    再提高有序顺序表的查找速度

    • 如果能够结合索引和折半查找,有序顺序表的查找速度可以比单纯的折半查找更加快
    • 假设有序顺序查找表元素有datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_折半查找_55
    • 根据前面的分析我们为每个索引块取大小datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_顺序查找_56
    • 此时共有恰好255项索引项在索引表中

    二叉查找树

    brief description:

    • if the node x to be find successor has its right subtree,the find the right subtree’s min
    • else(the node x do not has it’s right subtree(empty),then we simply go up the tree from x unitl we encounter a node that is the left child of its parent

    description from: intruduction to algorithm

    datastructre_查找_顺序查找/折半查找(二分查找)/分块查找性能_二叉查找树_查找前驱节点_概率论_57