• 算法导论 第六章 堆排序(python)


    6.1堆

    卫星数据:一个带排序的的数通常是有一个称为记录的数据集组成的,每一个记录有一个关键字key,记录的其他数据称为卫星数据。

    原地排序:在排序输入数组时,只有常数个元素被存放到数组以外的空间中去。

    在第二章介绍了两种排序:插入排序和合并排序,接下来两章要介绍的是推排序和快速排序,这四个排序都属于比较排序(comparison sort)。

    快速排序的性能一般优先于堆排序

    二叉堆是一个数组(b),近似完全二叉树(a)

    数组(b) 实际的存储形势

    二叉树(a) 要表达的结构

    clipboard[32]

    clipboard[33]

    [1,A.heap-size] 闭区间的范围是堆(python一0开始 选择 [0,A.heap-size+1]的数组 怎么舍弃第一位? -1 ? 0 ? )

    clipboard[34]

    PARENT 返回的i的父亲结点在数组b中的下标 如i = 2 ->PARENT(2) ==1

    LEFT 返回的i的左孩子结点在数组b中的下标 如i = 2 ->LEFT(2) ==4

    RIGHT 返回的i的右孩子结点在数组b中的下标 如i = 2 ->LEFT(2) ==5

    这3条是用数组(顺序表)表达堆(完全二叉树)的关键

    特别注明i(数组下标)必须是从1开始{python中我舍弃第一位 data = [-1,] }

    def PARENT(i):
    
        return i//2 #为什么是一半 参考离散数学和数据结构
    
                            #我的解释是:二叉树的性质+下标从1开始
    
    def LEFT(i):
    
        return i*2 #同上
    
    def RIGHT(i):
    
        return i*2 + 1 #同上
    最大堆定义:所以父结点比孩子结点大

    clipboard[35] #堆排序使用 关键所在 调堆和建堆都是保证他

    #堆排序就是将他的根节点{堆顶}取出来-->调堆-->将他的根节点{堆顶}取出来-->调堆-...直到堆只有一个数

    最小堆定义:所以父结点比孩子结点小

    clipboard[36]

    6.2维护堆的性质(调堆)

    讲A[i] 和他的2个孩子对比最大的放在A[i]的位置

    如果A[i]就是最大值的就结束

    否则交换A[i] 和A[x] 再递归调节x结点

    上图:

    clipboard[37]

    clipboard[38]

    clipboard[39]参考

    clipboard[40]

    class Mylist(list):
    
        def __init__(self):
    
            self.heap_size = 0
    
            super().__init__()
    
    def MAX_HEAPIFY(A,i):
    
        l = LEFT(i)
    
        r = RIGHT(i)
    
        #找出最大的结点
    
        #i的左孩子是否大于i
    
        #A.heap_size 写一个继承了list类 类中加上这个参数(Mylist)
    
        #或者选择A[0] 位放heap_size ??
    
        #或者设计全局变量
    
        if l <= A.heap_size and A[l] > A[i]:
    
            largest = l
    
        else:
    
            largest = i
    
        #和右孩子比
    
        if r <= A.heap_size and A[r] > A[largest]:
    
            largest = r
    
        if largest != i: #如果A[i]不是最大的 就要调堆了
    
            A[i],A[largest] = A[largest],A[i] #交换
    
            MAX_HEAPIFY(A,largest) #递归调largest
    6.3建堆

    从最后一个有子树的(图中坐标5 = 10//2)的结点向根节点(图中坐标1)调堆

    clipboard[41]

    def BUILD_MAX_HEAP(A):
    
        A.heap_size = len(A)-1
    
        #print(len(A))
    
        for i in range(A.heap_size//2,0,-1): #从n//2开始到1
    
            #print(i)
    
            MAX_HEAPIFY(A,i)

    clipboard[42]

    (在纸上画一遍就知道怎么回事了)

    O(n)

    6.4堆排序算法

    clipboard[43]

    建立最大堆后(如a)显然16(A[1])是最大的,取出最大的,再调堆,再取出最大的。。。。。

    clipboard[44]

    def HEAPSORT(A):
    
        BUILD_MAX_HEAP(A) #建堆
    
        print("建成的堆:",A)
    
        for i in range(len(A)-1,1,-1):
    
            A[1],A[i] = A[i],A[1] #第一位和最后有位换
    
            A.heap_size = A.heap_size - 1 #取出了一个
    
            MAX_HEAPIFY(A,1) #调堆        
    
    if __name__ == '__main__':
    
        A = Mylist()
    
        #print(type(A))
    
        for i in[-1,4,1,3,2,16,9,10,14,8,7]: #A = [,...] A会变成list
    
            A.append(i)
    
        #print(type(A))
    
        HEAPSORT(A)
    
        print("堆排序后:",A)
    
    '''
    
    ============== RESTART: F:pythonalgorithms6_2_max_heapify.py ==============
    
    建成的堆: [-1, 16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
    
    堆排序后: [-1, 1, 2, 3, 4, 7, 8, 9, 10, 14, 16]
    
    环境win7 + python3.5.1
    
    '''

    引用参考:

    http://blog.csdn.net/littlethunder/article/details/23877545

    http://www.wutianqi.com/?cat=515&paged=5

    http://blog.csdn.net/hanchengxi/article/details/8454754

  • 相关阅读:
    每种特定的迭代器如何使用
    常量迭代器
    容器迭代器
    三十分钟掌握STL
    高快省的排序算法
    FloatTest32 Example
    /浮点数的比较
    java第一天
    ACwing 898
    POJ 3268
  • 原文地址:https://www.cnblogs.com/liguan/p/5173394.html
Copyright © 2020-2023  润新知