python實現優先隊列(一)


學習了堆排序,使用python實現了一個優先隊列結構,記錄一下實現過程:

用一個python的list來表示堆結構,將list作為參數傳入構造函數中,然后在構造函數中建堆:

class prioQueue:
    def __init__(self, elist=[]):
        self._elems = list(elist)
        if elist:
            self.buildheap()

堆一般都是一個完全二叉樹,那么根據完全二叉樹的性質,一個節點i的左子節點為i+1,右子節點為i*2+1,以最小堆為例,根節點一定是最小值,優先隊列必須保證每次彈出的值都是最小的。建堆過程是一個遞歸的過程,首先拿出list中第一個元素,一個元素必然是一個堆,接下來從list最后拿2個元素分別作為2個子堆,若要將第一個元素這個堆和最后2個元素所構成的子堆合並成一個堆,那么就要保證堆頂的值最小,先判斷左右2個子堆的大小,然后用第一個元素和較小的比較,若小,則不變,若大,則將元素與子堆那個元素調換位置,這樣就形成了1個3個元素的最小堆,之后再從list中拿出第二個元素,從排序好的堆中一次進行這個步驟,若較小,則跳出循環拿出下一個元素,若較大則交換2個比較的元素,再用這個元素與2個子節點的元素進行比較,直到遍歷了整個二叉樹都沒有更大的元素,那么這個元素就將放在元素的最末尾。這便是一個從堆頂即二叉樹根節點開始向下掃描的過程,先定義這個siftDown方法:

def siftdown(self, e,begin, end):
        elems, i, j, = self._elems, begin , begin*2+1

e為要排序的元素,變量i 儲存我們開始排序的位置,為了不浪費空間,begin參數來作為排序好及位排好的元素list中的索引,所以一開始是0之后遞增,end參數代表着堆元素的個數,也就是len(list)。

然后我們用elems變量保存數組 i作為排序元素的指針 j為i的左子樹 進行循環。只要j沒有到最后就循環下去。

while j < end:

然后先比較左右子樹,使用較小的子樹來和插入的e做比較,若e小於它那么就找到位置,否則調換位置繼續與換位置后的左右子樹進行比較,i位置即是元素e所在的位置:

if j+1<end and elems[j+1] < elems[j]:
                j = j + 1         
            if e < elems[j]:
                break
            elems[i] = elems[j]
            i, j = j , 2*j+1
        elems[i] = e

對list的每一個元素都進行這樣的一個向下掃描,就可以完成一個建堆的過程,得到一個最小堆:

    def buildheap(self):
        end = len(self._elems)
        for i in range(end//2,-1,-1):
            self.siftdown(self._elems[i],i,end)
        return self._elems

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM