日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【数据结构】——堆排序

發布時間:2023/12/10 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【数据结构】——堆排序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

一、視頻鏈接:

二、隨筆筆記

?三、代碼實現(構造堆、向下調整)自定義+內置函數

四、堆排序之topk問題的應用


一、視頻鏈接:

https://www.bilibili.com/video/BV1mp4y1D7UP?p=19

https://www.bilibili.com/video/BV1mp4y1D7UP?p=20

https://www.bilibili.com/video/BV1mp4y1D7UP?p=21

https://www.bilibili.com/video/BV1mp4y1D7UP?p=22

https://www.bilibili.com/video/BV1mp4y1D7UP?p=23

...

https://www.bilibili.com/video/BV1mp4y1D7UP?p=29

二、隨筆筆記

?

?

?

?

?三、代碼實現(構造堆、向下調整)自定義+內置函數

''' 堆排序 排序過程: 1、構造堆,使得整個二叉樹是一個堆 2、挨個出數,首先得到堆頂的元素,堆頂元素是第一大元素 3、堆頂元素出數后,位置空出來了,將堆的最后一個元素放在堆頂,然后進行向下調整,使得堆再次有序 4、此時堆頂的元素是第二大元素 5、重復3,直到堆空,堆排序完成 '''# 向下調整函數,前提是堆頂結點的左右子樹已經是有序的大根堆 def sift(li,low,high):'''這里以大根堆為例,通過向下調整來使得堆有序,父節點比兩個子節點元素大,主要思想是通過比較根節點和兩個子節點的大小來進行調整,使得子節點總是小于其直接父節點:param li: 列表:param low: 堆頂位置:param high: 堆最后一個元素的位置:return: 沒有返回值,直接生成的是一個有序的堆,以列表1形式呈現'''tmp = li[low] # 堆頂元素i = low # 堆頂元素的位置j = 2 * i + 1 # 根節點i的左子節點位置while j <= high: # 保證有子節點# 首先比較兩個左右兩個子節點的大小,將更大的子節點元素和父節點進行比較if j+1 <= high and li[j] < li[j+1]: # 右子節點存在(j+1<high)并且右子節點更大j = j + 1 # 將j設置為節點大的那個位置#將更大子節點元素和父節點元素進行比較if tmp < li[j]: #父節點元素小于更大子節點元素li[i] = li[j] # 將大的子節點元素賦值給父節點i = j # 往下一層進行調整j = 2 * i + 1 # 更新j為新的父節點的左子節點# 如果父節點比更大的子節點元素還要大的話,那就說明已經使堆有序化了,# 注意這里的前提是父節點的左右子樹已經是有序的大根堆,因此當父節點不小于子節點時,就完成了堆有序化else:li[i] = tmp # 將當前的位置賦值為tmp的值break # 因為存在j還沒有到最后就完成了堆排序,這時候可以直接跳出循環else: # 當不存在子節點時,說明完成了堆有序化,這時候將tmp賦值給最后一個節點li[i] = tmp# 構建堆的函數,將堆構建成一個大根堆,注意這里的大根堆是完全二叉樹 def creatHeap(li):'''這是對無序的完全二叉樹進行有序化,使得完全二叉樹成為特殊的完全二叉樹,這里以大根堆為例:param li: 列表:return: 無返回值,直接對li進行了構建,因為列表是引用的方式進行訪問的,所以不需要返回列表調用函數后也發生了改變'''heapLen = len(li) # 堆的元素個數,這里指的是列表的長度# (heapLen - 2) // 2這里指的是通過子節點來獲得父節點的方法,//是指取整for rootNode in range((heapLen - 2) // 2,-1,-1): # 這里指的是遍歷所有的根節點,然后對每一個根節點的子樹進行有序化,向下調整sift(li,rootNode,heapLen - 1)# 堆排序 def heapSorted1(li):'''這個函數是自定義的函數主要思想:對大根堆進行排序,首先high指的是樹的最后一個位置,在這里也指的是未排序區的最后一個位置先對樹進行堆的有序化,然后交換堆頂和high位置的元素,此時high的位置向前進一個位置,直到high的位置為0時,說明此時未排序的元素就一個元素了,也就是完成了堆排序:param li: 列表:return: '''creatHeap(li) # 得到大根堆heapLen = len(li) # 獲得元素的個數high = heapLen - 1 # 未排序的最后一個元素的位置low = 0 # 堆頂位置while high != 0: # 當未排序的索引為0時,說明只是剩下一個元素,排序完成li[low],li[high] = li[high],li[low] # 堆頂和未排序最后一個元素進行合并high -= 1 # 未排序區縮小一個位置sift(li,low,high) # 對新的堆進行有序化def heapSorted2(li):'''路飛思想:語言更簡潔,但是個人覺得可讀性不太好,不如上面的編程:param li: 列表:return: '''creatHeap(li) # 得到大根堆heapLen = len(li) # 獲得元素的個數for i in range(heapLen-1,-1,-1):# i表示當前的堆的最后一個位置li[0],li[i] = li[i],li[0]sift(li,0,i - 1)def sysFun(li):'''這里使用了Python內置模塊:param li: 列表:return: '''import heapq # 這個實現的是小根堆heapq.heapify(li) # 構建小根堆liSorted = []for i in range(len(li)):popEle = heapq.heappop(li) # 每次彈出最小的元素liSorted.append(popEle) # 將彈出的元素加入到列表中,得到的就是排好序的列表(從小到大排序)return liSortedif __name__ == '__main__':import randomli1 = list(range(20)) # 隨機生成20個數li2 = list(range(20)) # 隨機生成20個數li3 = list(range(20)) # 隨機生成20個數random.shuffle(li1) # 打亂random.shuffle(li2) # 打亂random.shuffle(li3) # 打亂print(li1,"打亂后待排序的列表1")print(li2,"打亂后待排序的列表2")print(li3,"打亂后待排序的列表3")print("-------------------------------------------------------------------------")heapSorted1(li1)print(li1,"自己的代碼")print("-------------------------------------------------------------------------")heapSorted2(li2)print(li2,"路飛的代碼")print("-------------------------------------------------------------------------")liSorted = sysFun(li3)print(liSorted,"python內置模板")

[18, 5, 0, 3, 7, 11, 1, 6, 16, 10, 2, 14, 17, 8, 19, 12, 13, 4, 9, 15] 打亂后待排序的列表1
[16, 19, 18, 15, 11, 12, 5, 2, 6, 9, 10, 0, 1, 14, 8, 7, 13, 4, 17, 3] 打亂后待排序的列表2
[9, 11, 12, 16, 14, 3, 19, 6, 0, 5, 15, 8, 2, 1, 7, 13, 18, 17, 10, 4] 打亂后待排序的列表3
-------------------------------------------------------------------------
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 自己的代碼
-------------------------------------------------------------------------
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 路飛的代碼
-------------------------------------------------------------------------
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] python內置模板

四、堆排序之topk問題的應用

''' topk問題就是從n個數中取得前面k個大(小)的數 '''# 小根堆的向下調整方法 # 向下調整函數,前提是堆頂結點的左右子樹已經是有序的小根堆 def sift(li,low,high):'''這里以小根堆為例,通過向下調整來使得堆有序,父節點比兩個子節點元素小,主要思想是通過比較根節點和兩個子節點的大小來進行調整,使得子節點總是大于其直接父節點:param li: 列表:param low: 堆頂位置:param high: 堆最后一個元素的位置:return: 沒有返回值,直接生成的是一個有序的堆,以列表1形式呈現'''tmp = li[low] # 堆頂元素i = low # 堆頂元素的位置j = 2 * i + 1 # 根節點i的左子節點位置while j <= high: # 保證有子節點# 首先比較兩個左右兩個子節點的大小,將更小的子節點元素和父節點進行比較if j+1 <= high and li[j] > li[j+1]: # 右子節點存在(j+1<high)并且右子節點更小j = j + 1 # 將j設置為節點小的那個位置#將更小子節點元素和父節點元素進行比較if tmp > li[j]: #父節點元素小于更小子節點元素li[i] = li[j] # 將小的子節點元素賦值給父節點i = j # 往下一層進行調整j = 2 * i + 1 # 更新j為新的父節點的左子節點# 如果父節點比更小的子節點元素還要小的話,那就說明已經使堆有序化了,# 注意這里的前提是父節點的左右子樹已經是有序的小根堆,因此當父節點不大于子節點時,就完成了堆有序化else:li[i] = tmp # 將當前的位置賦值為tmp的值break # 因為存在j還沒有到最后就完成了堆排序,這時候可以直接跳出循環else: # 當不存在子節點時,說明完成了堆有序化,這時候將tmp賦值給最后一個節點li[i] = tmpdef creatHeap(li):'''這是對無序的完全二叉樹進行有序化,使得完全二叉樹成為特殊的完全二叉樹,這里以小根堆為例:param li: 列表:return: 無返回值,直接對li進行了構建,因為列表是引用的方式進行訪問的,所以不需要返回列表調用函數后也發生了改變'''heapLen = len(li) # 堆的元素個數,這里指的是列表的長度# (heapLen - 2) // 2這里指的是通過子節點來獲得父節點的方法,//是指取整for rootNode in range((heapLen - 2) // 2,-1,-1): # 這里指的是遍歷所有的根節點,然后對每一個根節點的子樹進行有序化,向下調整sift(li,rootNode,heapLen - 1)def heapSorted2(li):'''路飛思想:語言更簡潔,但是個人覺得可讀性不太好:param li: 列表:return: '''creatHeap(li) # 得到小根堆heapLen = len(li) # 獲得元素的個數for i in range(heapLen-1,-1,-1):# i表示當前的堆的最后一個位置li[0],li[i] = li[i],li[0]sift(li,0,i - 1)def topkPro(li,k):'''從列表中取前k個大的數字:param li: 列表:param k: 需要取的元素個數:return: 返回的是列表中最大的前k個數,但是不一定有序,如果要拍好序,可以在調用一次堆排序函數'''liK = li[0:k] # 取前k個數sift(liK,0,k-1) # 對前k個數構建小根堆for index in range(k,len(li)): # 遍歷循環不在堆里的元素if li[index] > liK[0]: # 比較與堆頂元素的大小liK[0] = li[index] # 若比堆頂元素大則替換堆頂元素sift(liK,0,k-1) # 重新構建小根堆heapSorted2(liK) # 對最后得到的k各元素進行排序return liKif __name__ == '__main__':import randomli = list(range(20)) # 隨機生成20個數random.shuffle(li) # 打亂print(li,"未排序的列表")print("---------------------------------------")heapSorted2(li)print(li,"堆排序后的列表")print("----------------------------------------")liK = topkPro(li,5)print(liK,"li列表中前k大的數")

[19, 18, 3, 15, 6, 4, 17, 7, 8, 9, 12, 5, 13, 14, 16, 0, 1, 2, 10, 11] 未排序的列表
---------------------------------------
[19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 堆排序后的列表
----------------------------------------
[19, 18, 17, 16, 15] li列表中前k大的數

總結

以上是生活随笔為你收集整理的【数据结构】——堆排序的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。