排序算法:堆排序


title: ‘排序算法:堆排序’
date: 2019-12-24 15:09:06
categories:

  • 算法導論
    tags:
  • 算法導論

堆排序

  • 堆排序思路是,首先構建一個堆,然後根和葉子節點進行交換,從而達到目的

  • 堆構建算法:

    def build_max_heap(heap):  # 構造一個堆,將堆中所有數據重新排序
        heapSize = len(heap)
        for i in range((heapSize -2)//2,-1,-1):  # 自底向上建堆
            max_heapify(heap, heapSize, i)
    
  • 堆排序算法:

    def heap_sort(heap):  # 將根節點取出與最後一位做對調,對前面len-1個節點繼續進行堆調整過程。
        build_max_heap(heap)
        # 調整後列表的第一個元素就是這個列表中最大的元素,將其與最後一個元素交換,然後將剩餘的列表再遞歸的調整爲最大堆
        for i in range(len(heap)-1, -1, -1):
            heap[0], heap[i] = heap[i], heap[0]
            max_heapify(heap, i, 0)
    
    

小根堆:

  • 堆調整算法:

    def max_heapify(heap,heapSize,root):  # 調整列表中的元素並保證以root爲根的堆是一個大根堆
        '''
        給定某個節點的下標root,這個節點的父節點、左子節點、右子節點的下標都可以被計算出來。
        父節點:(root-1)//2
        左子節點:2*root + 1
        右子節點:2*root + 2  即:左子節點 + 1
        '''
        left = 2*root + 1
        right = left + 1
        larger = root
        if left < heapSize and heap[larger] < heap[left]:
            larger = left
        if right < heapSize and heap[larger] < heap[right]:
            larger = right
        if larger != root:  # 如果做了堆調整則larger的值等於左節點或者右節點的值,這個時候做堆調整操作
            heap[larger], heap[root] = heap[root], heap[larger]
            # 遞歸的對子樹做調整
            max_heapify(heap, heapSize, larger)#下沉操作
    
  • 總體代碼:

    # 小根堆
    def max_heapify(heap,heapSize,root):  # 調整列表中的元素並保證以root爲根的堆是一個大根堆
        '''
        給定某個節點的下標root,這個節點的父節點、左子節點、右子節點的下標都可以被計算出來。
        父節點:(root-1)//2
        左子節點:2*root + 1
        右子節點:2*root + 2  即:左子節點 + 1
        '''
        left = 2*root + 1
        right = left + 1
        larger = root
        if left < heapSize and heap[larger] < heap[left]:
            larger = left
        if right < heapSize and heap[larger] < heap[right]:
            larger = right
        if larger != root:  # 如果做了堆調整則larger的值等於左節點或者右節點的值,這個時候做堆調整操作
            heap[larger], heap[root] = heap[root], heap[larger]
            # 遞歸的對子樹做調整
            max_heapify(heap, heapSize, larger)#下沉操作
    def build_max_heap(heap):  # 構造一個堆,將堆中所有數據重新排序
        heapSize = len(heap)
        for i in range((heapSize -2)//2,-1,-1):  # 自底向上建堆
            max_heapify(heap, heapSize, i)
    def heap_sort(heap):  # 將根節點取出與最後一位做對調,對前面len-1個節點繼續進行堆調整過程。
        build_max_heap(heap)
        # 調整後列表的第一個元素就是這個列表中最大的元素,將其與最後一個元素交換,然後將剩餘的列表再遞歸的調整爲最大堆
        for i in range(len(heap)-1, -1, -1):
            heap[0], heap[i] = heap[i], heap[0]
            max_heapify(heap, i, 0)
    
    # 測試
    if __name__ == '__main__':
        a = [30, 50, 57, 77, 62, 78, 94, 80, 84]
        print(a)
        heap_sort(a)
        print(a)
        # b = [random.randint(1,1000) for i in range(1000)]
        # print(b)
        # heap_sort(b)
        # print(b)
    
    

大根堆

  • 調整算法:

    def max_heapify(heap,heapSize,root):  # 調整列表中的元素並保證以root爲根的堆是一個大根堆
        '''
        給定某個節點的下標root,這個節點的父節點、左子節點、右子節點的下標都可以被計算出來。
        父節點:(root-1)//2
        左子節點:2*root + 1
        右子節點:2*root + 2  即:左子節點 + 1
        '''
        left = 2*root + 1
        right = left + 1
        larger = root
        if left < heapSize and heap[larger] > heap[left]:
            larger = left
        if right < heapSize and heap[larger] > heap[right]:
            larger = right
        if larger != root:  # 如果做了堆調整則larger的值等於左節點或者右節點的值,這個時候做堆調整操作
            heap[larger], heap[root] = heap[root], heap[larger]
            # 遞歸的對子樹做調整
            max_heapify(heap, heapSize, larger)
    
  • 總體代碼:

    # 大根堆
    def max_heapify(heap,heapSize,root):  # 調整列表中的元素並保證以root爲根的堆是一個大根堆
        '''
        給定某個節點的下標root,這個節點的父節點、左子節點、右子節點的下標都可以被計算出來。
        父節點:(root-1)//2
        左子節點:2*root + 1
        右子節點:2*root + 2  即:左子節點 + 1
        '''
        left = 2*root + 1
        right = left + 1
        larger = root
        if left < heapSize and heap[larger] > heap[left]:
            larger = left
        if right < heapSize and heap[larger] > heap[right]:
            larger = right
        if larger != root:  # 如果做了堆調整則larger的值等於左節點或者右節點的值,這個時候做堆調整操作
            heap[larger], heap[root] = heap[root], heap[larger]
            # 遞歸的對子樹做調整
            max_heapify(heap, heapSize, larger)
    def build_max_heap(heap):  # 構造一個堆,將堆中所有數據重新排序
        heapSize = len(heap)
        for i in range((heapSize -2)//2,-1,-1):  # 自底向上建堆
            max_heapify(heap, heapSize, i)
    def heap_sort(heap):  # 將根節點取出與最後一位做對調,對前面len-1個節點繼續進行堆調整過程。
        build_max_heap(heap)
        # 調整後列表的第一個元素就是這個列表中最大的元素,將其與最後一個元素交換,然後將剩餘的列表再遞歸的調整爲最大堆
        for i in range(len(heap)-1, -1, -1):
            heap[0], heap[i] = heap[i], heap[0]
            max_heapify(heap, i, 0)
    
    # 測試
    if __name__ == '__main__':
        a = [30, 50, 57, 77, 62, 78, 94, 80, 84]
        print(a)
        heap_sort(a)
        print(a)
        # b = [random.randint(1,1000) for i in range(1000)]
        # print(b)
        # heap_sort(b)
        # print(b)
    
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章