優先隊列
普通的隊列是一種先進先出的數據結構,元素在隊列尾追加,而從隊列頭刪除。在優先隊列中,元素被賦予優先級。當訪問元素時,具有最高優先級的元素最先刪除。優先隊列具有最高級先出 (largest-in,first-out)的行為特征。
在某些數據處理的例子中,總數據量太大,無法排序(甚至無法全部裝進內存)。例如,需要從十億個元素中選出最大的十個,你真的想把一個10億規模的數組排序嗎?但有了優先隊列,你只用一個能存儲十個元素的隊列即可。具體做法是讓元素一個個輸入,只要優先隊列的個數大于10,就不斷刪除最小元素,最后優先隊列長度不大于10時停止刪除,只剩10個自然就是所有元素中最大的10個了。很多情況我們會收集一些元素,處理當前鍵值最大(或最小)的元素,然后再收集更多的元素,再處理當前最大的(或最小的)元素,這可以看成我們按照事件的優先級順序來處理,生活中很多任務都是有優先級高低之分的,所以優先隊列可以高效地處理這些情況。
優先隊列最重要的操作是刪除最大元素和插入元素
優先隊列不同數據結構實現的優先級
數據結構 | 插入元素 | 刪除最大元素 |
---|---|---|
有序數組 | N | 1 |
無序數組 | 1 | N |
堆 | logN | logN |
理想情況 | 1 | 1 |
堆
數據結構的二叉堆能很好的實現優先隊列的基本操作。在二叉堆中,每個元素要保證大于等于另兩個特定位置的元素。
堆(heap)也被稱為優先隊列(priority queue)。隊列中允許的操作是先進先出(FIFO),在隊尾插入元素,在隊頭取出元素。而堆也是一樣,在堆底插入元素,在堆頂取出元素,但是堆中元素的排列不是按照到來的先后順序,而是按照一定的優先順序排列的。這個優先順序可以是元素的大小或者其他規則。如圖一所示就是一個堆,堆優先順序就是大的元素排在前面,小的元素排在后面,這樣得到的堆稱為最大堆。最大堆中堆頂的元素是整個堆中最大的,并且每一個分支也可以看成一個最大堆。同樣的,我們可以定義最小堆,如圖二所示。
插入元素
向堆中插入一個新元素;在堆的最末尾插入新結點。然后自下而上調整子結點與父結點:比較當前結點與父結點,不滿足堆性質則交換,使得當前子樹滿足二叉堆的性質。時間復雜度為 O(logn)。
刪除最大元素
刪除堆頂元素,再把堆存儲的最后那個結點填在根結點處。再從上而下調整父結點與它的子結點。時間復雜度為 O(logn)。