欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python實現(xiàn)堆排序案例詳解

 更新時間:2021年09月10日 09:05:54   作者:Python碎片  
這篇文章主要介紹了Python實現(xiàn)堆排序案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下

Python實現(xiàn)堆排序

一、堆排序簡介

堆排序(Heap Sort)是利用堆這種數(shù)據(jù)結構所設計的一種排序算法。

堆的結構是一棵完全二叉樹的結構,并且滿足堆積的性質:每個節(jié)點(葉節(jié)點除外)的值都大于等于(或都小于等于)它的子節(jié)點。

關于二叉樹和完全二叉樹的介紹可以參考:http://www.dbjr.com.cn/article/222487.htm

堆排序先按從上到下、從左到右的順序將待排序列表中的元素構造成一棵完全二叉樹,然后對完全二叉樹進行調整,使其滿足堆積的性質:每個節(jié)點(葉節(jié)點除外)的值都大于等于(或都小于等于)它的子節(jié)點。構建出堆后,將堆頂與堆尾進行交換,然后將堆尾從堆中取出來,取出來的數(shù)據(jù)就是最大(或最小)的數(shù)據(jù)。重復構建堆并將堆頂和堆尾進行交換,取出堆尾的數(shù)據(jù),直到堆中的數(shù)據(jù)全部被取出,列表排序完成。

堆結構分為大頂堆和小頂堆:

1. 大頂堆:每個節(jié)點(葉節(jié)點除外)的值都大于等于其子節(jié)點的值,根節(jié)點的值是所有節(jié)點中最大的,所以叫大頂堆,在堆排序算法中用于升序排列。

2. 小頂堆:每個節(jié)點(葉節(jié)點除外)的值都小于等于其子節(jié)點的值,根節(jié)點的值是所有節(jié)點中最小的,所以叫小頂堆,在堆排序算法中用于降序排列。

二、堆排序原理

堆排序的原理如下:

1. 將待排序列表中的數(shù)據(jù)按從上到下、從左到右的順序構造成一棵完全二叉樹。

2. 將完全二叉樹中每個節(jié)點(葉節(jié)點除外)的值與其子節(jié)點(子節(jié)點有一個或兩個)中較大的值進行比較,如果節(jié)點的值小于子節(jié)點的值,則交換他們的位置(大頂堆,小頂堆反之)。

3. 將節(jié)點與子節(jié)點進行交換后,要繼續(xù)比較子節(jié)點與孫節(jié)點的值,直到不需要交換或子節(jié)點是葉節(jié)點時停止。比較完所有的非葉節(jié)點后,即可構建出堆結構。

4. 將數(shù)據(jù)構造成堆結構后,將堆頂與堆尾交換,然后將堆尾從堆中取出來,添加到已排序序列中,完成一輪堆排序,堆中的數(shù)據(jù)個數(shù)減1。

5. 重復步驟2,3,4,直到堆中的數(shù)據(jù)全部被取出,列表排序完成。

以列表 [10, 17, 50, 7, 30, 24, 27, 45, 15, 5, 36, 21] 進行升序排列為例。列表的初始狀態(tài)如下圖。

要進行升序排序,則構造堆結構時,使用大頂堆。

1. 將待排序列表中的數(shù)據(jù)按從上到下、從左到右的順序構造成一棵完全二叉樹。

2. 從完全二叉樹的最后一個非葉節(jié)點開始,將它的值與其子節(jié)點中較大的值進行比較,如果值小于子節(jié)點則交換。24是最后一個非葉子節(jié)點,它只有一個子節(jié)點21,24大于21,不需要交換。

3. 繼續(xù)將倒數(shù)第二個非葉節(jié)點的值與其子節(jié)點中較大的值進行比較,如果值小于子節(jié)點則交換。節(jié)點30有兩個子節(jié)點5和36,較大的是36,30小于36,交換位置。

4. 重復對下一個節(jié)點進行比較。7小于45,交換位置。

5. 繼續(xù)重復,50大于27,不需要交換位置。如果不需要進行交換,則不用再比較子節(jié)點與孫節(jié)點。

6. 繼續(xù)重復,17小于45,交換位置。

7. 17和45交換位置之后,17交換到了子節(jié)點的位置,還需要繼續(xù)將其與孫節(jié)點進行比較。17大于15,不需要交換。

8. 繼續(xù)對下一個節(jié)點進行比較,10小于50,交換位置。

9. 10和50交換位置之后,10交換到了子節(jié)點的位置,還需要繼續(xù)將其與孫節(jié)點進行比較。10小于于27,交換位置。

10. 此時,一個大頂堆構造完成,滿足了堆積的性質:每個節(jié)點(葉節(jié)點除外)的值都大于等于它的子節(jié)點。

11. 大頂堆構建完成后,將堆頂與堆尾交換位置,然后將堆尾從堆中取出。將50和21交換位置,交換后21到了堆頂,50(最大的數(shù)據(jù))到了堆尾,然后將50從堆中取出。

12. 將50從堆中取出后,找到了待排序列表中的最大值,50添加到已排序序列中,第一輪堆排序完成,堆中的元素個數(shù)減1。

13. 取出最大數(shù)據(jù)后,重復將完全二叉樹構建成大頂堆,交換堆頂和堆尾,取出堆尾。這樣每次都是取出當前堆中最大的數(shù)據(jù),添加到已排序序列中,直到堆中的數(shù)據(jù)全部被取出。

14. 循環(huán)進行 n 輪堆排序之后,列表排序完成。排序結果如下圖。

三、Python實現(xiàn)堆排序

# coding=utf-8
def heap_sort(array):
    first = len(array) // 2 - 1
    for start in range(first, -1, -1):
        # 從下到上,從右到左對每個非葉節(jié)點進行調整,循環(huán)構建成大頂堆
        big_heap(array, start, len(array) - 1)
    for end in range(len(array) - 1, 0, -1):
        # 交換堆頂和堆尾的數(shù)據(jù)
        array[0], array[end] = array[end], array[0]
        # 重新調整完全二叉樹,構造成大頂堆
        big_heap(array, 0, end - 1)
    return array
 
 
def big_heap(array, start, end):
    root = start
    # 左孩子的索引
    child = root * 2 + 1
    while child <= end:
        # 節(jié)點有右子節(jié)點,并且右子節(jié)點的值大于左子節(jié)點,則將child變?yōu)橛易庸?jié)點的索引
        if child + 1 <= end and array[child] < array[child + 1]:
            child += 1
        if array[root] < array[child]:
            # 交換節(jié)點與子節(jié)點中較大者的值
            array[root], array[child] = array[child], array[root]
            # 交換值后,如果存在孫節(jié)點,則將root設置為子節(jié)點,繼續(xù)與孫節(jié)點進行比較
            root = child
            child = root * 2 + 1
        else:
            break
 
 
if __name__ == '__main__':
    array = [10, 17, 50, 7, 30, 24, 27, 45, 15, 5, 36, 21]
    print(heap_sort(array))

運行結果:

[5, 7, 10, 15, 17, 21, 24, 27, 30, 36, 45, 50]

代碼中,先實現(xiàn)一個big_heap(array, start, end)函數(shù),用于比較節(jié)點與其子節(jié)點中的較大者,如果值小于子節(jié)點的值則進行交換。代碼中不需要真正將數(shù)據(jù)都添加到完全二叉樹中,而是根據(jù)待排序列表中的數(shù)據(jù)索引來得到節(jié)點與子節(jié)點的位置關系。完全二叉樹中,節(jié)點的索引為i,則它的左子節(jié)點的索引為2*i+1,右子節(jié)點的索引為2*i+2,有n個節(jié)點的完全二叉樹中,非葉子節(jié)點有n//2個,列表的索引從0開始,所以索引為0~n//2-1的數(shù)據(jù)為非葉子節(jié)點。

實現(xiàn)堆排序函數(shù)heap_sort(array)時,先調用big_heap(array, start, end)函數(shù)循環(huán)對非葉子節(jié)點進行調整,構造大頂堆,然后將堆頂和堆尾交換,將堆尾從堆中取出,添加到已排序序列中,完成一輪堆排序。然后循環(huán)構建大頂堆,每次將最大的元素取出,直到堆中的數(shù)據(jù)全部被取出。

四、堆排序的時間復雜度和穩(wěn)定性

1. 時間復雜度

在堆排序中,構建一次大頂堆可以取出一個元素,完成一輪堆排序,一共需要進行n輪堆排序。每次構建大頂堆時,需要進行的比較和交換次數(shù)平均為logn(第一輪構建堆時步驟多,后面重建堆時步驟會少很多)。時間復雜度為 T(n)=nlogn ,再乘每次操作的步驟數(shù)(常數(shù),不影響大O記法),所以堆排序的時間復雜度為 O(nlogn) 。

2. 穩(wěn)定性

在堆排序中,會交換節(jié)點與子節(jié)點,如果有相等的數(shù)據(jù),可能會改變相等數(shù)據(jù)的相對次序。所以堆排序是一種不穩(wěn)定的排序算法。

到此這篇關于Python實現(xiàn)堆排序案例詳解的文章就介紹到這了,更多相關Python實現(xiàn)堆排序內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 利用Python如何制作貪吃蛇及AI版貪吃蛇詳解

    利用Python如何制作貪吃蛇及AI版貪吃蛇詳解

    這篇文章主要給大家介紹了關于利用Python如何制作貪吃蛇及AI版貪吃蛇的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-08-08
  • Python獲取Linux系統(tǒng)下的本機IP地址代碼分享

    Python獲取Linux系統(tǒng)下的本機IP地址代碼分享

    這篇文章主要介紹了Python獲取Linux系統(tǒng)下的本機IP地址代碼分享,本文直接給出實現(xiàn)代碼,可以獲取到eth0等網(wǎng)卡的IP地址,需要的朋友可以參考下
    2014-11-11
  • Python獲取圖像中像素點坐標實例代碼

    Python獲取圖像中像素點坐標實例代碼

    當我們處理圖像的時候避免不了要對訪問,或是讀取某一個像素點的值,下面這篇文章主要給大家介紹了關于利用Python如何獲取圖像中像素點坐標的相關資料,需要的朋友可以參考下
    2022-06-06
  • Python如何快速實現(xiàn)分布式任務

    Python如何快速實現(xiàn)分布式任務

    這篇文章主要介紹了Python如何快速實現(xiàn)分布式任務,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • Pyecharts繪制可視化地球實現(xiàn)示例

    Pyecharts繪制可視化地球實現(xiàn)示例

    這篇文章主要為大家介紹了Pyecharts繪制可視化地球實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • 5款最強且免費的Python IDE小結

    5款最強且免費的Python IDE小結

    開發(fā)工具在日常代碼編寫過程中起著至關重要的作用,一款優(yōu)秀的開發(fā)工具,不僅可以盡可能的減少你在配置方面耗費的精力,本文主要介紹了5種,感興趣的可以了解一下
    2021-07-07
  • python使用win32com庫播放mp3文件的方法

    python使用win32com庫播放mp3文件的方法

    這篇文章主要介紹了python使用win32com庫播放mp3文件的方法,涉及Python使用win32com庫操作音頻文件的相關技巧,需要的朋友可以參考下
    2015-05-05
  • 如何利用Python實現(xiàn)一個論文降重工具

    如何利用Python實現(xiàn)一個論文降重工具

    文章去重(或叫網(wǎng)頁去重)是根據(jù)文章(或網(wǎng)頁)的文字內容來判斷多個文章之間是否重復,下面這篇文章主要給大家介紹了關于利用Python實現(xiàn)論文降重工具的相關資料,需要的朋友可以參考下
    2021-07-07
  • Python issubclass和isinstance函數(shù)的具體使用

    Python issubclass和isinstance函數(shù)的具體使用

    本文主要介紹了Python issubclass和isinstance函數(shù)的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-02-02
  • Python實現(xiàn)判斷一個字符串是否包含子串的方法總結

    Python實現(xiàn)判斷一個字符串是否包含子串的方法總結

    這篇文章主要介紹了Python實現(xiàn)判斷一個字符串是否包含子串的方法,結合實例形式總結分析了四種比較常用的字符串子串判定方法,需要的朋友可以參考下
    2017-11-11

最新評論