zoukankan      html  css  js  c++  java
  • Algorithms

    概念
        堆(heap): 
            堆是一个数组, 它可以被看成一个近似的完全二叉树. 树的每一个结点对应数组中的一个元素. 树的根节点是 A[1] 堆包含2个属性 A.length 表示数组A中元素的个数, A.heap_size 表示数组A中存储的堆元素的个数. 也就是说: 虽然 A[1,.., length] 可能都存在数据, 但是只有 A[1,…, heap_size]中存放的属于堆属性的元素.
        
        最大堆, 最小堆(max heap, min heap): 
            最大堆的性质是指除了根以外的所有节点 i 都要满足:
                A[parent(i)] >= A[i]    
            也就是说, 莫个节点的值至多与其父节点一样大.
            
            最小堆正好相反: 
                A[parent(i)] <= A[i]
            
            在排序算法中, 使用的是最大堆。最小堆通常用于构造优先队列。
    Python programming
       

          1 , 各结点下标的维护(父节点 parent, 左子结点 left, 右子结点 right): 

    def parent(i):
                return i // 2
    
            def left(i):
                return 2*i
    
            def right(i):
                return 2*i + 1  

    2.  创建 max_heap(A, i) 函数. 它的输入为一个数组A 和一个下标 i. 在函数被调用之前, 假定前提是 left(i) 和 right(i) 都已经是最大堆. 也就是说调用一次 max_heap(A, i), 操作一个A[i]到正确的位置上( i, left(i) 和 right(i) ). 函数通过让 A[i] 值在最大堆中'逐级下降', 从而使得以A[i]为根结点的子树满足最大堆的性质.
    
    def max_heapify(A, i, heap_size): # 这里 heap_size 参数, 而并不是属性实现的.
        l = left(i)
        r = right(i)
        if l <= heap_size and A[l-1] > A[i-1]:
            largest = l
        else:
            largest = i
        if r <= heap_size and A[r-1] > A[largest-1]:
            largest = r
        if largest != i:
            A[i-1], A[largest-1] = A[largest-1], A[i-1]
            max_heapify(A, largest, heap_size)
    
    if __name__ == '__main__':
        A = [16,4,10,14,7,9,3,2,8,1]
        print('Before: ',A)
        max_heapify(A,2,10)
        print('After: ', A)
    
    结果打印:
        Before:  [16, 4, 10, 14, 7, 9, 3, 2, 8, 1]
        After:  [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]

    3. 通过 build_max_heap(A) 处理 数组 A 满足最大堆属性.
    
    def build_max_heap(A):
        heap_size = len(A)
        for i in range(1, heap_size//2+1):      # 这里遍历次 heap_size // 2, 因为在函数 max_heapify 已经处理了 heap_size // 2 个元素(通过递归调用的方式)  
            max_heapify(A,heap_size//2 + 1 - i,heap_size)
            print('Factory: ', A)
    
    结果打印:
        Before:  [4, 1, 3, 2, 16, 9, 10, 14, 8, 7]
        Factory:  [4, 1, 3, 2, 16, 9, 10, 14, 8, 7]
        Factory:  [4, 1, 3, 14, 16, 9, 10, 2, 8, 7]
        Factory:  [4, 1, 10, 14, 16, 9, 3, 2, 8, 7]
        Factory:  [4, 16, 10, 14, 7, 9, 3, 2, 8, 1]
        Factory:  [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
        After:  [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]

    4.  创建 heapsort(A) 函数. 在步骤3中 build_max_heap(A) 将 A 创建成立了最大堆. 这个时候数组A中的最大元素是 A[1], 所以保持将最大堆 A 中的 A[1] 和 A[n]进行互换, 并重复这一互换过程 ( n = n - i, i = [1…, n-2] ), 即可完成了排序. 注意: 每一次互换之前要保证输入数组A的最大堆性质, 这一点可以通过调用 max_heap(A, 1)来保证.
    
    def heap_sort(A):
        build_max_heap(A)
        n = heap_size = len(A)
    
        for i in range (2, n+1):
            print('Step ', i - 1)
            A[0], A[n-i+1] = A[n-i+1], A[0]
            heap_size -= 1
            max_heapify(A,1, heap_size)
            print(A)
    
    if __name__ == '__main__':
        A = [4,1,3,2,16,9,10,14,8,7]
        print('Before: ', A)
        heap_sort(A)
        print('After: ', A)
    
    结果打印:
    
    Before:  [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
    Step  1
        [14, 8, 10, 4, 7, 9, 3, 2, 1, 16]
    Step  2
        [10, 8, 9, 4, 7, 1, 3, 2, 14, 16]
    Step  3
        [9, 8, 3, 4, 7, 1, 2, 10, 14, 16]
    Step  4
        [8, 7, 3, 4, 2, 1, 9, 10, 14, 16]
    Step  5
        [7, 4, 3, 1, 2, 8, 9, 10, 14, 16]
    Step  6
        [4, 2, 3, 1, 7, 8, 9, 10, 14, 16]
    Step  7
        [3, 2, 1, 4, 7, 8, 9, 10, 14, 16]
    Step  8
        [2, 1, 3, 4, 7, 8, 9, 10, 14, 16]
    Step  9
        [1, 2, 3, 4, 7, 8, 9, 10, 14, 16]
    After:  [1, 2, 3, 4, 7, 8, 9, 10, 14, 16] 

    Reference, 
      Introduction to algorithms
  • 相关阅读:
    算法-对分查找(二分查找)C++实现
    Android Studio简单设置
    一起talk C栗子吧(第八回:C语言实例--素数)
    Maven生命周期
    java8_api_日期时间
    UITableviewcell的性能问题
    iOS开发25个性能调优技巧
    iOS9新特性
    iOS9 3DTouch、ShortcutItem、Peek And Pop技术一览
    iOS网络访问之使用AFNetworking
  • 原文地址:https://www.cnblogs.com/zzyzz/p/12869256.html
Copyright © 2011-2022 走看看