8.基於二叉堆的優先佇列演算法
其實根據已經看到的虛擬碼來說,感覺它的計算方式還是很簡單的,主要還是基於原有二叉堆的實現演算法上進行一定程度的改造,一個是入隊演算法,就是指新增一個元素到原有陣列之中,該陣列本來已經實現了二叉堆,一開始先將新增的元素放置在陣列最尾部,也就是二叉堆的最後一個三角節點處,開始進行上級父節點的比較,不斷的比較最終確定其位置。另一個是出隊演算法,這個就比較簡單了,跟前面的堆排序其實差不多,就是每次提取出整個二叉堆的根(可能是最大值或者是最小值)。
演算法虛擬碼:
ENQUEUE(Q,e) //入隊
1. if heap-size[Q] > length[Q]
2. then error" 堆上溢"
3. i<-heap-size[Q]<-heap-size[Q]+1
4. A[heap-size[Q]]<-e
5. while i>1 and A[PARENT(i)]<A[i]
6. do exchange A[i] <->A[PARENT(I)]
7. i <- PARENT(I)
DEQUEUE(Q)
1. if heap-size[Q] <1
2. then error "堆上溢"
3. max<-Q[l] //這裡Q[l]是指原二叉堆的根(可能是最大值或是最小值)
4. Q[l] <-Q[heap-size[Q]]
5. heap-size[Q] <-heap-size[Q]-1
6. MAX-HEAPIFY(Q,1)
7. return max
C++:
main.cpp
#include <iostream> #include<algorithm> #include<iterator> #include<functional> #include<vector> #include<queue> using namespace std; int main(){ int a[]={5,1,9,4,6,2,0,3,8,7},i; string b[]={"ChongQing","ShangHai","AoMen","TianJin","BeiJing","XiangGang"}; double c[]={8.5,6.3,1.7,9.2,0.5,2.3,4.1,7.4,5.9,3.7}; priority_queue<int,vector<int>,less<int>> p;//這部分就是定義了一個能實現二叉堆優先出入隊的變數p,大值提取到父節點 for(i=0;i<10;i++) p.push(a[i]);//這部分就是入隊,每次入隊都會進行一次堆實現 while(!p.empty()){ //只要變數p不為空,迴圈就會一直進行下去 cout<<p.top()<<" "; //將該堆的根輸出 p.pop(); //將除去堆根之後的資料再推入變數p中進行堆實現 } cout<<endl; priority_queue<double,vector<double>,greater<double>> p1;//這部分就是定義了一個能實現二叉堆優先出入隊的變數p,小值提取到父節點(這裡呼叫的是STL中的優先出入隊) for(i=0;i<10;i++) p1.push(c[i]); while(!p1.empty()){ cout<<p1.top()<<" "; p1.pop(); } cout<<endl; }
JAVA:
Test.java
package test;
import java.util.*;
public class Test{ public static void main(String[] args){ Integer a[]={5,1,9,4,6,2,0,3,8,7},i; PriorityQueue q=new PriorityQueue (10,new Less());//這裡利用了java中Collection Framework中的模板,其中less表示提取最大值到父節點 PriorityQueue q1=new PriorityQueue();//預設的話就是將最小值提取到父節點 for(i=0;i<10;i++) { q.add(a[i]);//進行入隊 q1.add(a[i]); } while(!q.isEmpty())//只要陣列不為空 System.out.print(q.poll()+" ");//進行出隊 System.out.println(); while(!q1.isEmpty()) System.out.print(q1.poll()+" "); System.out.println(); } }