成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

淺析經典排序算法之堆排序

開發 前端 算法
堆通常是一個可以被看做一棵樹(完全)的數組對象。

堆通常是一個可以被看做一棵樹(完全)的數組對象。且總是滿足以下規則:

堆是一棵完全二叉樹

節點總是大于(或小于)它的孩子節點。

因此,根據第二個特性,就把二叉堆分為大頂堆(或叫最大堆),和小頂堆(或叫最小堆)。

在上圖中,1 2 是大頂堆 ,3 4 是小頂堆。判斷是不是堆的條件:「從根結點到任意結點路徑上結點序列的有序性!大頂堆和小頂堆判斷序列是順序還是逆序!」

Python并沒有提供“堆”這種數據類型,它是直接把列表當成堆處理的。Python提供的heapq包中有一些函數,提供執行堆操作的工具函數

  1. >>> import heapq 
  2. >>> heapq.__all__ 
  3. ['heappush''heappop''heapify''heapreplace''merge''nlargest''nsmallest''heappushpop'

堆排序

往堆中插入一個元素后,我們就需要進行調整,讓其重新滿足堆的特性,這個過程叫做堆化(heapify)。

那么堆排序的基本思路是怎么樣的呢?

  1. 將待排序序列構建成一個堆 H[0……n-1],根據(升序降序需求)選擇大頂堆或小頂堆;
  2. 把堆首(最大值)和堆尾互換;
  3. 順著節點所在的路徑,向上或者向下,對比,然后交換,目的是把新的數組頂端數據調整到相應位置;

下面舉個例子(資源來自王爭算法),比如在上面的大頂堆中添加數據22。


堆化非常簡單,就是順著節點所在的路徑,向上或者向下,對比,然后交換。

堆排序的刪除操作,這里一般指的是堆頂元素,當我們刪除堆頂元素之后,就需要把第二大的元素放到堆頂,那第二大元素肯定會出現在左右子節點中。

然后我們再迭代地刪除第二大節點,以此類推,直到葉子節點被刪除。但是這樣會產生一個數組空洞的問題。


因此,這里面又個技巧,就是刪除堆頂元素的時候,不能直接刪除,要用堆頂元素和最后一個元素做交換,然后根據堆的特點調整堆,直到滿足條件。

排序的過程就是每次待排序的序列長度減去1再執行這兩步。

下面給出通過Python中的heapq模塊實現的堆排序簡單代碼。

  1. from heapq import heappop, heappush 
  2.  
  3. def heap_sort(array): 
  4.     heap = [] 
  5.     for element in array: 
  6.         heappush(heap, element) 
  7.  
  8.     ordered = [] 
  9.  
  10.     while heap: 
  11.         ordered.append(heappop(heap)) 
  12.     return ordered 
  13.  
  14. array = [13, 21, 15, 5, 26, 4, 17, 18, 24, 2] 
  15. print(heap_sort(array)) 
  16. # [2, 4, 5, 13, 15, 17, 18, 21, 24, 26] 

如果不使用heapq模塊,對于推排序需要了解堆排序中的建堆過程。

將數組原地建成一個堆。不借助另一個數組,就在原數組上操作。建堆的過程,有兩種思路。

第一種建堆思路的處理過程是從前往后處理數組數據,并且每個數據插入堆中時,都是從下往上堆化。而第二種實現思路,是從后往前處理數組,并且每個數據都是從上往下堆化。


  • 補充:利用層序遍歷(遍歷方式還有前中后)映射到數組后,假設樹或子樹的根節點為arr[root],則其對應的子節點分別為arr[root*2+1],arr[root*2+2]。

也就是如果節點的下標是 i,那左子節點的下標就是 2∗i+1,右子節點的下標就是 2∗i+2,父節點的下標就是 。

  1. def heap_sort(array): 
  2.     n = len(array) 
  3.     # 從尾部開始建堆,這樣保證子節點有序 
  4.     for i in range((n-1)//2, -1, -1): 
  5.         _shift(array, n, i) 
  6.     # 依次把堆頂元素交換到最后,重建堆頂(堆不包含剛交換的最大元素) 
  7.     for i in range(n-1, 0, -1): 
  8.         array[0], array[i] = array[i], array[0] 
  9.         _shift(array, i, 0) 
  10.     return array 
  11.  
  12. # 重建堆頂元素 n:堆元素個數,i:堆建頂位置 
  13. def _shift(array, n, i): 
  14.     # 如果沒有子節點,直接返回 
  15.     if i*2+1 >= n: 
  16.         return 
  17.     # 取最大子節點位置 
  18.     maxsub = i*2+2 if i*2+2 < n and array[i*2+1] <= array[i*2+2] else i*2+1 
  19.     # 如果節點小于最大子節點,交換元素,遞歸以子節點為堆頂重建 
  20.     if array[i] < array[maxsub]: 
  21.         array[i], array[maxsub] = array[maxsub], array[i] 
  22.         _shift(array, n, maxsub) 
  23.  
  24. if __name__ == '__main__'
  25.     array = [13, 21, 15, 5, 26, 4, 17, 18, 24, 2] 
  26.     print(heap_sort(array)) 
  27.      
  28. # [2, 4, 5, 13, 15, 17, 18, 21, 24, 26] 

堆排序不是穩定的排序算法,因為在排序的過程,存在將堆的最后一個節點跟堆頂節點互換的操作,所以就有可能改變值相同數據的原始相對順序。堆排序整體的時間復雜度是O(nlogn)  。

參考資料 https://github.com/MaoliRUNsen/runsenlearnpy100

 

責任編輯:姜華 來源: Python之王
相關推薦

2011-04-20 15:06:44

堆排序

2014-10-30 15:59:10

2009-08-11 09:19:52

C#選擇排序C#算法

2011-04-20 16:58:33

java排序

2023-10-10 08:00:07

2021-03-23 08:33:22

Java數據結構算法

2021-01-21 05:22:36

排序算法選擇

2021-01-26 05:33:07

排序算法快速

2011-04-11 14:52:18

選擇排序排序C++

2021-01-20 06:09:30

堆排序TopK應用場景

2021-11-05 22:47:44

冒泡排序選擇插入

2011-04-20 11:22:51

Java

2021-10-31 07:38:37

排序算法代碼

2023-10-05 09:01:05

插入排序對象序列log2i

2022-11-21 07:58:10

Java排序冒泡排序

2021-06-09 09:06:52

Go語言算法

2015-10-20 15:09:55

排序算法

2011-04-20 13:56:08

選擇排序

2011-04-20 14:07:37

冒泡排序

2011-04-20 14:19:00

希爾排序
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久999精品 | 国产精品精品久久久 | 婷婷色综合 | 久久久久久亚洲精品 | 久久精品成人热国产成 | 久久久久无码国产精品一区 | 国产男女视频 | 国产日韩精品一区二区三区 | 色一级| 国产成人精品一区二区 | 综合九九 | 四虎影院免费在线 | 久久爱综合 | 一区二区三区视频 | 中文字幕一区二区三区在线乱码 | 国产精品av久久久久久毛片 | 久久久精品一区二区 | 色资源站 | 亚洲国产精品久久 | 精品日本久久久久久久久久 | 欧美日本久久 | 偷拍自拍在线观看 | 中文字幕一区二区三区在线观看 | 亚洲自拍偷拍欧美 | 国产精品99久久久久久动医院 | 久久夜色精品国产 | 一区二区三区视频在线观看 | 色婷婷久久久亚洲一区二区三区 | 午夜一区二区三区 | 91午夜在线 | 91久久国产综合久久 | 亚洲成人av| 在线欧美一区二区 | 小早川怜子xxxxaⅴ在线 | 久久久久久一区 | 久久久高清 | 精品免费国产 | 操操日| 色婷婷一区二区三区四区 | 久久久噜噜噜www成人网 | 国产精品久久久爽爽爽麻豆色哟哟 |