c語言堆排序解析__c語言

來源:互聯網
上載者:User

堆排序

在堆排序中,我們可以將順序表看成一顆完全的二叉樹

二叉樹知識回顧:

 從1開始對二叉樹中的每個節點順序編號

 

序列 : [  # , C, H, G, E, A, D, I, F, B, K ]

索引             1   2  3  4  5  6  7  8  9  10

 

 

所以編號為 i 的 左孩子節點編號為 2*i  ; 右孩子節點編號為 2*i+ 1,

除了根節點,如果一個節點編號為 j  那麼���的雙親節點為    j//2 

如果將序列R[1,n] 視作一個完全二叉樹,那麼  R[i] 的左孩子是R[2i] 右孩子則為R[2i+1]

堆:

n個值的序列K[1],K[2],K[3]……K[n] 稱之為堆。

該序列滿足一下特性

大根堆: K[i] >= K[2*i] 且 K[i] > = K[2*i +1]     i 的範圍 1 ~ n//2

小根堆: K[i] <= K[2*i] 且 K[i] <= K[2*i +1] 

 

如圖所示

      小根堆

 

 

    大根堆

 

 

 

堆排序的簡單過程是:

1、根據序列,構建一個初始堆   (大根堆/小根堆)

2、交換堆的第一個和最後一個元素。

3、排除最後一個元素,將序列第一個到倒數第二個重新整理成 堆。

4、再次交換堆的第一個和最後一個元素

5、重複 第3 步

6 、重複上述過程直至完成排序

 

再說簡單點就是:構造堆,交換元素、構造堆,交換元素,構造堆。。。。。。

 

從上述 6步的第三步——交換第一個和最後一個元素,而且該動作會在每次整理完堆之後,都會重複進行。所以我們就知道,序列的最後一個元素總是當前堆的最大/最小元素。所以,第一步,我們究竟是要構建大根堆還是小根堆,是要看我們打算順序排序序列還是要倒序排序序列。

 

在下面的例子中我們 順序排序 序列,也就說 構建 大根堆。

有這樣一個序列

A  = [ –,   1,  0,  3,  6,  2,  8,  4,  9,  7,  5 ]

構建二叉樹,樹節點從 1  開始 編號。所以A[0] 為佔位作用。初始二叉樹如下:

 

 

 

 開始構建大根堆。

1、從最後一個非葉子節點開始。比較 節點 和它的 最大 孩子節點,如果 如果節點大,那麼就保持不變。如果孩子節點大,那麼就交換孩子節點和該節點的值。

在本例中,最後一個非葉子節點是 序號為 5,值為 2 的節點。比較它和它的最大孩子節點。發現5 >2 所以交換他和他的孩子。

2、然後查看倒數第二個非葉子節點,也就是 序號為4 值為 6 的節點。同樣比較它和它的最大孩子節點。發現,6<9 也需要交換[下圖中紅色部分]

3、然後繼續查看倒數第三個非葉子節點,也就是 序號為 3 值為3 的節點,同樣比較它和它的最大孩子節點,發現 8>3 ,也需要交換[下圖中灰色部分]

 

4,然後繼續比較倒數第四個非葉子節點。即 序號為2 值為 0 的 節點。比較它和它的最大孩子節點  ,發現0<9,交換2者。。。。。 莫急,你再往下看會發現即使0 和 9 交換了,0還是比它現在的最大孩子節點(7)小,所以,還要繼續交換 0 和7 最終結果就是下圖:

 

 5,接下來移動序號為1,值為1 的節點。。。重複上述過程,最終構造出的大根堆如下:

這就是完成構造初始堆的過程。函數如下:

def fixDown(a, i, n):  # i 是指當前節點 n 為序列中所有元素的最大索引。二叉樹中 最後一個節點的 序號    while 2 * i <= n:   # j = 2*i  即 當前節點的左孩子。它必須在所有節點的序號範圍內。如果j > n 了說明 i 是葉子節點。        j = 2 * i        if j < n and a[j] < a[j + 1]:  # 選出左右孩子節點中更大的那個。注意一:下面詳說。            j += 1        if a[i] < a[j]: # 如果雙親節點小於孩子節點,那麼交換雙親節點和子節點。同時向下移動 i 的位置。i 的範圍是[1-n//2]            a[i], a[j] = a[j], a[i]            i = j        else:  #如果雙親節點大於他的最大的孩子,那麼說明這個小的二叉樹構建堆完成。            break

View Code

注意一: 這條語句中使用了短路原則。即:如果 j < n 為假那麼就不再對後面的條件進行判斷。直接跳過該條件陳述式,進行下面的語句。為什麼在本條件陳述式中 要求 j != n,在本例中 j = 10,如果 條件陳述式改成 j<= n ,10 <=10,第一個條件成立了,那麼無疑會繼續驗證第二個條件是否成立,然而對照本例你會發現,根本沒有第11個節點,即a[j+1] 是不存在的。所以這會給程式引發一個超出索引的錯誤。

 

 

初始化堆的,同時也是整理堆的函數有了,那麼接下來就是在堆排序的主函數中調用這個函數,進行堆排序了,還是先用圖示範一下,再給代碼。

回顧一下上述的 堆排序的過程 。構造堆已經完成了,那麼就該交換第一個節點和最後一個節點了。然後,將最後一個節點排除,用剩下的節點再次構建堆。

 

重新構造堆如下:

交換第一個和最後一個如下:

 

 

 重複上面的過程直至再也沒有可以構建堆的節點了。排序完成。

代碼如下:

def heapSort(A):    n = len(A) - 1  # 因為加入了一個佔位元素,所以構建堆的實際元素個數應該 減去 1    for i in range(n // 2, 0, -1):  #構建初始堆。 從最後一個非葉子節點開始構建堆。地板除 1是為了防止出現小數,2是取下界。        fixDown(A, i,n)     # 調用上面的那個構造堆的函數,構造出初始化堆。    print('A=',A)           #這裡可以看一下 初始化堆之後的序列的 各個元素的排列順序    while n > 1:           # n 表示 堆的最後一個節點的序號        A[1], A[n] = A[n], A[1]   #  交換堆的第一個和最後一個 節點        fixDown(A, 1, n-1)     #  重新整理堆剩下的節點,再次構建 根堆        n -= 1                # 每次交換之後,已經排好序的節點就被排除出堆,所以堆的最後一個節點的向前移動一位。    return A[1:]             #因為我們使用了佔位元素,所以返回從 所以為 1 及其以後得元素。A = [ '--',   1,  0,  3,  6,  2,  8,  4,  9,  7,  5 ] # 第一個元素不用,佔位print(heapSort(A))

View Code

 

 

 

 

這裡再說一下:

因為我們是從小到大排列 序列。所以每次都是讓 讓  A[i] 和他子節點中比較大的那個進行比較,然後大的上浮,小的下沉。從而構建大根堆

 

如果我們想要從大到小 逆序排列的話

那麼就要讓 A[i] 和它 的子節點中 較小的那個比較,小的上浮,大的下沉。

所以 構造堆的代碼如下:

def fixDown(a, i, n):  # i 是指當前節點 n 為序列中所有元素的最大索引。二叉樹中 最後一個節點的 序號    while 2 * i <= n:   # j = 2*i  即 當前節點的左孩子。它必須在所有節點的序號範圍內。如果j > n 了說明 i 是葉子節點。        j = 2 * i        if j < n and a[j] > a[j + 1]:  # 選出左右孩子節點中更 。。小。。  的那個            j += 1        if a[i] > a[j]: # 如果雙親節點。。 大於 。。孩子節點,那麼交換雙親節點和子節點。同時向下移動 i 的位置。i 的範圍是[1-n//2]            a[i], a[j] = a[j], a[i]            i = j        else:  #如果雙親節點。。小於。。他的。。最小。。的孩子,那麼說明這個小的二叉樹構建堆完成。            break

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.