優先佇列學習總結

2021-09-18 01:22:00 字數 2964 閱讀 3972

佇列:

現實中我們最常見的是,去醫院**,去銀行取錢,一般都需要排隊,這就是佇列,佇列有乙個最顯著的特徵: 先進先出,一般情況下,大多都是先到先辦理,但是也是有特殊的情況,例如在醫院,萬一來個急診的,一定是急診的優先,或者在銀行,來個vip,有綠色通道。 這種特殊的情況下,就是佇列中的特殊的佇列:優先佇列。它的實現方法:給入隊的元素,賦予乙個優先順序,根據優先順序,將其插入佇列中,(不是插入佇列的末尾)

比較器:

根據優先順序插入元素,這個過程一定需要進行比較它們的優先順序,因此我們需要複寫compare比較方法 ,一般情況下寫乙個匿名類實現comparator介面中compare方法的即可。下面有乙個簡單例子可供參考。

優先佇列:

用的儲存是二叉樹的邏輯,應該叫完全二叉樹,也可以叫做最大堆。

二叉樹顧名思義就像一棵樹,每個節點下最多可以掛兩個節點,如圖:

在優先佇列中儲存的方式就是 queue = ;

若當前節點下標為i   那麼它的子節點  左側 = 2*i+1  右側 = 2*i +2。優先佇列顧名思義,就是優先權最大的排在佇列的頭部,而優先權的判斷是根據物件的compare方法比較獲取的,保證根節點的優先順序一定比子節點的優先順序大。所以放入到優先佇列的元素要麼實現了comparable介面,要麼在創造這個優先佇列時,指定乙個比較器。

下面我們來看一下優先佇列的建構函式:

private static final int default_initial_capacity = 11;

private final comparator super e> comparator;

public priorityqueue()

public priorityqueue(int initialcapacity,

comparator super e> comparator)

1、往佇列中新增乙個物件

public boolean add(e e) 

public boolean offer(e e)

2、擴充套件長度

private void grow(int mincapacity)
3、設定size+1。如果是空的優先佇列,就把新元素新增到佇列頭部。如果不是空,那就根據compareto來判斷新加入的元素的優先級別,那麼我們來看一下siftup方法

private void siftup(int k, e x) 

private void siftupcomparable(int k, e x)

queue[k] = key;

}private void siftupusingcomparator(int k, e x)

queue[k] = x;

}

如果在建立佇列的時候,指定了比較工具,那麼就用比較器,比較器內部實現,可以根據自己的定義的比較原則,也可以呼叫加入佇列的元素的compareto方法(如果實現的話),比較方法變化自行定義。

我們主要看一下沒有比較器的排序方法siftupcomparable,如下圖:

假設數字越小,優先級別越高,k的位置是新插入元素將要放置的位置,加入插入的是 25,那麼此元素的優先級別小於它的父節點的優先順序,直接把25放在k的位置。假如放置的是8,優先級別最高,所以 (k-1)>>>1 獲取父節點,與父節點比較,發現優先順序大於父節點,把父節點的值放入k, 把k的位置設定成父節點的下標值,遞迴查詢父節點,定位出k的位置,把新元素放入此位置。此種二叉樹演算法大大降低了演算法複雜度。

4、取走佇列頭部元素

public e poll() 

private void siftdown(int k, e x)

private void siftdowncomparable(int k, e x)

queue[k] = key;

}private void siftdownusingcomparator(int k, e x)

queue[k] = x;

}

如果佇列之有乙個元素,就彈出這個元素,設定--size的位置為null。如果不是乙個元素,彈出第乙個元素,獲取陣列最後的乙個元素,開始呼叫siftdown(0, x);我們先來看一下**:

這樣到poll掉佇列頭部元素後,佇列長度減一,所以最後的那個元素32的位置需要設定成null,這樣一來,需要填補佇列的頭,由於子節點一定小於等於父節點的優先順序,獲取父節點的子節點

int child = (k << 1) + 1;    // 獲取左子節點的下標

object c = queue[child];  // 獲取左子節點

int right = child + 1;          // 獲取右子節點的下標

但右子節點不一定存在所以下面做了乙個右節點不會為null的判斷,不為null的情況下,獲取兩個節點中優先順序高的乙個

if (right < size &&((comparable super e>) c).compareto((e) queue[right]) > 0)

public class main

};queuepq = new priorityqueue<>(cmp);

int n = in.nextint();

a = new node [n];

for (int i = 0; i < n; i++)

while (!pq.isempty())

}}

優先佇列學習總結

普通的佇列,遵循先進先出的規則,進行元素的新增和查詢,但是對於很多情況下,我們想要在序列中找符合我們要求的元素 比如序列中最大的元素 這時候,無論是普通的線性表還是線性表中比較特殊的棧或者佇列,找到該指定元素的範圍都會卡在時間複雜度為o n 的級別,其實我們完全可以實現查詢時間複雜度降為o 1 就是...

優先佇列學習

一 相關定義 優先佇列容器與佇列一樣,只能從隊尾插入元素,從隊首刪除元素。但是它有乙個特性,就是佇列中最大的元素總是位於隊首,所以出隊時,並非按照先進先出的原則進行,而是將當前佇列中最大的元素出隊。這點類似於給佇列裡的元素進行了由大到小的順序排序。元素的比較規則預設按元素值由大到小排序,可以過載 操...

佇列 優先佇列的學習

佇列定義 佇列是限定只能在表尾進行 插入,在表頭進行刪除的線性表 隊尾 允許插入的一端 隊頭 允許刪除的一端 佇列的定義 include queue 標頭檔案 using namespace std 需要加上使用名稱 空間,和sort 排序函式是一樣的。queue int q 格式 queue 型別...