• 堆和堆排序


    堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。

    两种类型的概念如下:
    大根堆(最大堆):每个结点的值都大于或等于左右孩子结点
    小根堆(最小堆):每个结点的值都小于或等于左右孩子结点

    以大根堆为例子:【堆是无序的】

     堆的三种操作:插入,删除,构建。

    假设已经存在下面的一个堆,给当前的堆添加一个节点0。【从最后一个位置,插入。顺序是:从左到右,由上到下】

     最后结果为:

     那么删除一个节点的话:比如在原来的堆上删除一个堆顶1.【从堆的顶部开始删除】

     然后将最后一个叶子节点,调到根堆上。形成非小根堆后,进行调整为小根堆如下图:

     最后:

     构建二叉堆,也就是把一个无序的完全二叉树调整为二叉堆,本质上就是让所有非叶子节点依次下沉

    将一颗无序的转换成小根堆

     结果:

    二叉堆虽然是一颗完全二叉树,但它的存储方式并不是链式存储,而是顺序存储。换句话说,二叉堆的所有节点都存储在数组当中。
    为什么堆适合采用顺序存储结构?由于堆是一棵完全二叉树,所以适宜采用顺序存储结构,这样能够充分利用存储空间。

    正因为是顺序存储,使得二叉堆有更好的查询能力。假设父节点的下标是parent,那么它的左孩子下标就是 2*parent+1;它的右孩子下标就是  2*parent+2 

    因而在此基础上有了堆排序:【大根堆为例子:是一次由大根堆到小根堆的转化得到的结果。】

    1. 把无序数组构建成二叉堆。

    2. 循环删除堆顶元素,移到集合尾部,调节堆产生新的堆顶。(实际上并不是完全删除,而是替换到最后面)

    下面我们来看下堆排序的思想是怎样的(以大根堆为例):

    #沿左,右子节点较大者依次往下调整
    def MAX_Heapify( array, HeapSize,root ):#在堆中做结构调整使得父节点的值大于子节点
        left = 2*root + 1
        right = left + 1
        larger = root
        if left < HeapSize and array[larger] < array[left]:
            larger = left
        if right < HeapSize and array[larger] <array[right]:
            larger = right
        if larger != root:#如果做了堆调整则larger的值等于左节点或者右节点的,这个时候做对调值操作
            array[larger],array[root] = array[root],array[larger]
            MAX_Heapify(array,HeapSize,larger)
     
    #创建堆
    def Build_MAX_Heap( array ):#构造一个堆,将堆中所有数据重新排序
        HeapSize = len( array )#将堆的长度单独拿出来方便
        for i in range( HeapSize // 2 - 1, -1, -1 ):#从后往前出数
            MAX_Heapify( array,HeapSize, i)
     
    #大顶堆排序
    def HeapSort( array ):#将根节点取出与最后一位做对调,对前面len-1个节点继续进行对调整过程。
        Build_MAX_Heap( array )
        #交换堆顶与最后一个结点,再调整堆
        for i in range(len(array) - 1, -1, -1 ):
            array[0], array[i] = array[i], array[0]
            MAX_Heapify(array, i, 0)
        return array
     
    a = [ -3, 1, 3, 0, 9, -9, 11, 82, 7 ]
    print(HeapSort(a))
    View Code

    堆排序与快速排序的区别:

    同:都是不稳定排序,两者的平均时间复杂度为nlogn

    不同:在最坏的情况下:时间复杂度:前者为nlogn,后者在n^2

               空间复杂度:前者为n,后者为1

  • 相关阅读:
    [luogu P2184] 贪婪大陆 [树状数组][线段树]
    luogu P3373 【模板】线段树 2
    [luogu P3384] 【模板】树链剖分 [树链剖分]
    树链剖分膜版
    AtCoder Grand Contest 026F
    AtCoder Regular Contest 091F
    AtCoder Regular Contest 099F
    AtCoder Grand Contest 027D
    向量叉积分配律简单证明
    LOJ 538. 「LibreOJ NOIP Round #1」数列递推(找规律+结论)
  • 原文地址:https://www.cnblogs.com/topass123/p/12664380.html
Copyright © 2020-2023  润新知