Python資料結構——二叉堆的實現
優先佇列的二叉堆實現
在前面的章節裡我們學習了“先進先出”(FIFO)的資料結構:佇列(Queue)。佇列有一種變體叫做“優先佇列”(Priority Queue)。優先佇列的出隊(Dequeue)操作和佇列一樣,都是從隊首出隊。但在優先佇列的內部,元素的次序卻是由“優先順序”來決定:高優先順序的元素排在隊首,而低優先順序的元素則排在後面。這樣,優先佇列的入隊(Enqueue)操作就比較複雜,需要將元素根據優先順序儘量排到佇列前面。我們將會發現,對於下一節要學的圖演算法中的優先佇列是很有用的資料結構。
我們很自然地會想到用排序演算法和佇列的方法來實現優先佇列。但是,在列表裡插入一個元素的時間複雜度是O(n),對列表進行排序的時間複雜度是O(nlogn)。我們可以用別的方法來降低時間複雜度。一個實現優先佇列的經典方法便是採用二叉堆(Binary Heap)。二叉堆能將優先佇列的入隊和出隊複雜度都保持在O(logn)。
二叉堆的有趣之處在於,其邏輯結構上像二叉樹,卻是用非巢狀的列表來實現。二叉堆有兩種:鍵值總是最小的排在隊首稱為“最小堆(min heap)”,反之,鍵值總是最大的排在隊首稱為“最大堆(max heap)”。在這一節裡我們使用最小堆。
二叉堆的操作
二叉堆的基本操作定義如下:
-
BinaryHeap():建立一個空的二叉堆物件
-
insert(k):將新元素加入到堆中
-
findMin():返回堆中的最小項,最小項仍保留在堆中
-
delMin():返回堆中的最小項,同時從堆中刪除
-
isEmpty():返回堆是否為空
-
size():返回堆中節點的個數
-
buildHeap(list):從一個包含節點的列表裡建立新堆
下面所示程式碼是二叉堆的示例。可以看到無論我們以哪種順序把元素新增到堆裡,每次都是移除最小的元素。我們接下來要來實現這個過程。