隊列的特點是先進先出。通常都把隊列比喻成排隊買東西,大家都很守秩序,先排隊的人就先買東西。 但是優先隊列有所不同,它不遵循先進先出的規則,而是根據隊列中元素的優先權,優先權最大的先被取出。通常把優先隊列比喻成現實生活中的打印。一個打印店里有很多打印機,每臺機器的性能不一樣,有的打印機打印很快,有的打印機打印速度很慢。當這些打印機陸陸續續打印完自己的任務時進入排隊等候狀態。如果我這個時候要打印一份文件,我選的不是第一個排隊的打印機,而是性能最好,打印最快的打印機。 優先隊列的特點就是將存儲的元素根據其優先權的高低,先取出優先權高的元素。所以,優先隊列的實現方法有很多。 如果優先權的范圍是已知的,那么就可以嘗試用一個二維數組來實現優先隊列。每一行表示一個優先級別。例如用大小為a[10][10]的二維數組來實現一個優先隊列,a[0]表示一個優先級別,里面存放優先級為0的元素,a[10]則存放優先級最高的元素。這樣根據元素的優先級進行存儲,取出元素的時候,根據優先級,先取出優先級最高的元素。 上面的方法在優先權范圍已知且比較集中可以估計的情況下可以適用,但是如果優先權的范圍不清楚,或者間隔很大,就不再使用。實現優先隊列也可以用一個鏈表隊列加以實現。鏈表的節點數據包含兩個部分,隊列的數據項和該數據項的優先權。將元素存入鏈表,需要用時,遍歷鏈表,查找優先權最大的數據項。 還可以用下面的方法。用一個數組來存放優先權,另外一個相應的數組存放要存放的元素。由于,不同的元素可能會有相同的優先權。所以,存放元素的數組中不是直接存放元素,而是存放鏈表,就像用掛鏈法來解決哈希沖突一樣。當有相同優先權的元素不止一個時,則掛在相應數組索引位置的鏈表上,如圖1。根據優先權數組中存放的優先權,來取得優先權最大的元素。由于數組查找比鏈表要快,所以,這個方法比上面的方法的改進。
Java代碼 收藏代碼 Java代碼
private int [] priority
private ElementNode[] elements
private int highest
private int manyItems
private int PriotityCount
private int [] priority
private ElementNode[] elements
private int highest
private int manyItems
private int PriotityCount
priority數組是用來存放優先權的,初始的值都是0,之后賦予的優先權值必須都大于0。
Elements是用來存放元素鏈表的數組。初始值都是null,然后往里面掛上鏈表。
highest元素是記錄優先權最大的元素的數組索引位置,這樣,可以方便使用,提高效 率。因為每次要查找優先權最大的元素時,不需要再重新查找。
manyItems用來記錄隊列中已經存放的元素個數。
PriotityCount用來記錄不同優先權的數目。因為有鏈表的存在,manyItems不能衡量 數組是否滿了,而PriotityCount對應的是優先權數組中的使用優先權個數,可以衡量數 組使用情況。
兩個私有方法:
Java代碼
private int getHighest (){}
private int contains (
int priority){}
private int getHighest (){}
private int contains (
int priority){}
private int getHighest (){}方法是用來取得隊列中優先權最大的元素的數組索引位 置。
private int contains(int priority){}方法是用來查找隊列中是否存在指定優先 權。如果存在,返回優先權所在的數組索引位置,如果不存在,則返回-1。
三個公有方法:
Java代碼
public Object getFront(){} public void insert(Object item, int priority){} public Object removeFront(){}
public Object getFront(){}
public void insert(Object item, int priority){}
public Object removeFront(){}
public Object getFront(){}方法是用來取得優先權最大的元素的。 public void insert(Object item, int priority){}方法是用來往隊列中添加元素 的。衡量優先權的標準可以很多,這里是直接要求用戶在存儲元素的時候存儲優先權。這個 隊列也還沒有考慮隊列滿了以后擴充的情況,所以如果滿了會報錯。在插入元素時,先要查 看這個元素所對應的優先權是否已經存在,如果已經存在了,那就直接掛到相應數組索引位 置的鏈表下面。如果不存在,則存放在一個還沒有存放值的數組位置中。如果加入元素成 功,要檢查是否比原來最大的優先權還要大,如果是,則把highest標記為這個新插入元素 的索引位置。 public Object removeFront(){}方法是用來刪除優先權最大的元素的。刪除成功時, 會返回被刪除的元素值,否則返回null。刪除優先權最大的元素后,還要查找出新的優先 權最大的值,并且讓highest指向這個值的索引位置。
示例代碼:
Java代碼
package cn.priorityQueue; /** * 這個優先隊列是基于數組的。 * 實現方法是,用兩個數組,一個存放元素的權限,另外一個存放元素的值,兩個數組的位置相互對應。 * 往這個隊列中存儲元素,需要放入兩個值,一個是元素的優先級值,另外一個是元素的值 * @author William Job * */
public class PriorityQueue01 { //這個數組priority用來表示每個元素的優先權 private int[] priority; //這個數組element用來存儲每個元素的值 private ElementNode[] elements; //這個值highest用來指向最高優先權的元素 private int highest = 0; //manyItems用來計數已經存儲的元素個數 private int manyItems; //PriorityCount用來計數已經存儲的優先權個數 private int PriotityCount;
public PriorityQueue01 (
int initialCapacity){ priority =
new int [initialCapacity]; elements =
new ElementNode[initialCapacity]; manyItems =
0 ; PriotityCount =
0 ; }
/** * 這個方法是用來取得優先權最大的值的。 * @throws IllegalAccessException * @return :返回擁有最大優先權的值 */ public Object
getFront (){
if (manyItems ==
0 ){
throw new IllegalArgumentException(
"沒有元素!" ); }
return elements[highest].element; }
/** * 這個方法用來向隊列中添加一個元素 * 在這個優先隊列的實現中,必須同時給定元素的值和元素的優先值 * @param item:元素的值 * @param priority:元素的優先值,必須大于0 * @throws Exception */ public void insert (Object item,
int priority){
if (PriotityCount >=
this .priority.length){
throw new IllegalArgumentException(
"隊列已滿" ); }
if (priority <=
0 ){
throw new IllegalArgumentException(
"優先權必須大于0!" ); }
int add = contains(priority);
if (add >=
0 ){ ElementNode node =
new ElementNode(); node.element = item; node.link = elements[add]; elements[add] = node; manyItems ++; }
else { ElementNode node =
new ElementNode(); node.element = item;
if (
this .priority[PriotityCount] ==
0 ){ elements[PriotityCount] = node; add = PriotityCount; }
else {
for (
int j =
0 ; j <
this .priority.length; j ++){
if (
this .priority[j] ==
0 ){ add = j; } } elements[add] = node; }
this .priority[add] = priority; manyItems ++; PriotityCount ++; }
if (
this .priority[add] >
this .priority[highest]){ highest = add; } }
/** * 這個方法是用來取得隊列中優先權最大的元素的 * @return :返回優先權最大的元素的索引位置 */ private int getHighest (){
int index = -
1 ;
int temp =
0 ;
for (
int i =
0 ; i < priority.length; i ++){
if (priority[i] > temp){ temp = priority[i]; index = i; } }
return index; }
/** * 這個方法用來查找隊列中是否已經存在這個優先權 * @param priority:要查找的優先權 * @return :如果這個優先權已經存在則返回這個優先權相應的索引位置,如果不存在則返回-1 */ private int contains (
int priority){
int index = -
1 ;
for (
int i =
0 ; i < PriotityCount; i ++){
if (
this .priority[i] == priority){ index = i; } }
return index; }
/** * 這個方法用來刪除優先權最大的元素,同時返回這個元素。 * 當刪除這個元素后,如果這個索引位置再也沒有相應的元素,則這個索引位置的優先權賦值為0 * @return :隊列中優先權最大的元素 */ public Object
removeFront (){ ElementNode temp = elements[highest];
if (elements[highest].link !=
null ){ elements[highest] = elements[highest].link; }
else { elements[highest] =
null ; priority[highest] =
0 ; PriotityCount --; } highest = getHighest(); manyItems --;
return temp.element; }
}
package cn.priorityQueue;
/** * 這個是元素的節點類。 * 這個類中有兩個屬性: * element存放元素的值,link指向下一個節點 * @author William Job * */
public class ElementNode { public Object element;
public ElementNode link;
public Object
getElement () {
return element; }
public void setElement (Object element) {
this .element = element; }
public Object
getLink () {
return link; }
public void setLink (ElementNode link) {
this .link = link; }
}
總結
以上是生活随笔 為你收集整理的优先队列的一种实现 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。