堆排序 Python實現(轉)

堆排序

堆排序是一種樹形選擇排序,是對直接選擇排序的有效改進。
基本思想:
堆的定義如下:具有n個元素的序列(k1,k2,…,kn),當且僅當滿足

情形1:ki <= k2i 且ki <= k2i+1 (最小化堆或小頂堆:左、右子孩子的值比父結點的值都大)
情形2:ki >= k2i 且ki >= k2i+1 (最大化堆或大頂堆:左、右子孩子的值比父結點的值都小)
其中i=1,2,…,n/2向下取整;

(1)]時稱之爲堆。由堆的定義可以看出,堆頂元素(即第一個元素)必爲最小項(小頂堆)。若以一維數組存儲一個堆,則堆對應一棵完全二叉樹,且所有非葉結點的值均不大於(或不小於)其子女的值,根結點(堆頂元素)的值是最小(或最大)的。如:
(a)大頂堆序列:(96, 83,27,38,11,09)
(b) 小頂堆序列:(12,36,24,85,47,30,53,91)

初始時把要排序的n個數的序列看作是一棵順序存儲的二叉樹(一維數組存儲二叉樹),調整它們的存儲序,使之成爲一個堆,將堆頂元素輸出,得到n 個元素中最小(或最大)的元素,這時堆的根節點的數最小(或者最大)。然後對前面(n-1)個元素重新調整使之成爲堆,輸出堆頂元素,得到n 個元素中次小(或次大)的元素。依此類推,直到只有兩個節點的堆,並對它們作交換,最後得到有n個節點的有序序列。稱這個過程爲堆排序
因此,實現堆排序需解決兩個問題:1. 如何將n 個待排序的數建成堆;2. 輸出堆頂元素後,怎樣調整剩餘n-1 個元素,使其成爲一個新堆。
首先討論第二個問題:輸出堆頂元素後,對剩餘n-1元素重新建成堆的調整過程。調整小頂堆的方法:
1)設有m 個元素的堆,輸出堆頂元素後,剩下m-1 個元素。將堆底元素送入堆頂((最後一個元素與堆頂進行交換),堆被破壞,其原因僅是根結點不滿足堆的性質。
2)將根結點與左、右子樹中較小元素的進行交換。
3)若與左子樹交換:如果左子樹堆被破壞,即左子樹的根結點不滿足堆的性質,則重複方法 (2).
4)若與右子樹交換,如果右子樹堆被破壞,即右子樹的根結點不滿足堆的性質。則重複方法 (2).
5)繼續對不滿足堆性質的子樹進行上述交換操作,直到葉子結點,堆被建成。

稱這個自根結點到葉子結點的調整過程爲篩選。
再討論對n 個元素初始建堆的過程。建堆方法:對初始序列建堆的過程,就是一個反覆進行篩選的過程。
1)n 個結點的完全二叉樹,則最後一個結點是第[n/2]個結點的子樹。
2)篩選從第[n/2]個結點爲根的子樹開始,該子樹成爲堆。
3)之後向前依次對各結點爲根的子樹進行篩選,使之成爲堆,直到根結點。

"""
堆排序   沒有實現
"""
def showarr(a):
    n = len(a);
    for i in range(n):
        print(a[i],end=" ")
    print("\n")


def build_heap(a):
    i = (len(a)-1)//2
    while i>=0:
        heap_adjust(a,i,len(a))
        i = i-1
    return a

def heap_adjust(h,s,n):
    print(s)
    temp = h[s]
    child = 2*s+1 ##左孩子節點 根節點從0開始,右孩子節點是child+1
    while child < n:
        if child+1<n and h[child] <h[child+1]: ##如果右孩子節點大於左孩子(找到比當前待調整節點大的孩子節點)
            child = child + 1
        if h[s]<h[child]: #如果較大的子節點大於父結點
            h[s] = h[child] #教大的子節點往上移動
            s = child
            child = 2*s+1
        else:
            break;
        h[s] = temp ##當前節點放到比它大的孩子節點上

    showarr(h)


def heap_sort(a):
    h = build_heap(a)
    i = len(a) -1 #從最後一項開始
    while i>=0:
        temp = h[i]
        h[i] = h[0]
        h[0] = temp
        heap_adjust(h,0,i)
        i= i-1

if __name__ == '__main__':
    a = [3,1,5,6,7,4,9,13,6,8,10]
    heap_sort(a)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章