原文鏈接:http://blog.csdn.net/coder_xia/article/details/6627902
如堆一樣,隊列也有2種,最大優先級隊列和最小優先級隊列。最大優先級隊列的一個應用是在一臺分時計算機上進行作業調度(終於搞到點有用的),對於最大優先級隊列,支持以下操作:
1)INSERT(S,x)把元素x插入隊列S
2)MAXIMUM(S):返回S中最大元素
3)EXTRACT-MAX(S):去掉並返回S中最大元素
4)INCRESE-KEY(S,x,key)在x位置插入值key。
優先級隊列,用堆實現,這就是看到的必殺運用了。
我們以82頁圖爲例
示範程序如下:
- //============================================================================
- // Name : prioity.cpp
- // Author : xia
- // Version : 1.0
- // Copyright : NUAA
- // Description : 優先級隊列的模擬實現
- //============================================================================
- #include <iostream>
- #include <climits> //INT_MIN
- #include <vector> //vector
- #include <algorithm>//for_each
- using namespace std;
- int Parent(int i)
- {//返回i節點的父節點
- if (i>0)
- return i/2;
- return -1;
- }
- void MaxHeapify(vector<int> &v ,int i ,int heap_size)
- {//讓A[i]在最大堆中下降,使以i爲根的子樹成爲大頂堆
- int left=2*i; //l<-LEFT(i)
- int right = 2*i+1; //r<-RIGHT(i)
- int largest=i;
- if ( (left <= heap_size) && (v[left] > v[i]) )
- largest = left ;
- else
- largest = i;
- if ( (right <=heap_size ) && (v[right] > v[largest]) )
- largest = right;//從父母和自己中找出最大的
- if (largest != i)
- {
- swap(v[i],v[largest]);//交換使i和子堆滿足堆性質,不過largest爲根的可能違反,遞歸調整
- MaxHeapify(v,largest, heap_size);
- }
- }
- void BuildHeap(vector<int> &v)
- {//建堆
- for (int i=v.size()/2 ; i > 0 ; i--)
- MaxHeapify(v,i,v.size()-1);
- }
- int HeapMaximum(vector<int> A)
- { //返回堆上的最大元素
- return A[1];
- }
- int HeapExtractMax(vector<int> &A )
- { //去掉並返回A中最大的值
- int heap_size = A.size()-1;
- if ( heap_size <1 )
- {
- cout << " heap underflow" << endl;
- exit(EXIT_FAILURE);
- }
- int max = A[1];
- A[1] = A[heap_size];
- heap_size--;
- A.pop_back();
- MaxHeapify(A,1 ,heap_size);
- return max;
- }
- void HeapIncreaseKey(vector<int> &A , int i, int key)
- { //在i處插入值爲key的數,並調整堆
- if (key<A[i])
- {
- cout << " new key is smaller than current key " << endl;
- exit(EXIT_FAILURE);
- }
- A[i] = key;
- while ( (i>1) && (A[Parent(i)] < A[i]))
- {
- swap(A[i],A[Parent(i)]);
- i = Parent(i) ;
- }
- }
- void MaxHeapInsert(vector<int> &A , int key)
- {
- A.push_back(INT_MIN); //僞代碼heapsize+1,且插入負無窮
- HeapIncreaseKey(A,A.size()-1,key);//第二個參數實際爲堆大小
- }
- template <class T>
- class Print
- {
- public:
- void operator () (T& t)
- {
- cout << t << " ";
- }
- };
- const int heap_size = 10; //這裏假設元素爲10個
- int main()
- {
- int temp[heap_size]={16,14,10,8,7,9,3,2,4,1};
- vector<int> v(temp+0,temp+heap_size);
- Print<int> print;
- v.insert(v.begin(),0);//插入個0,切合僞代碼
- BuildHeap(v); //雖然我們的數組順序已經符合堆,不過常理還是要先建堆
- cout << "初始堆V " << endl;
- for_each(v.begin()+1,v.end(),print);//遍歷輸出
- cout << endl<< endl;
- cout <<"插入個試試 " << endl;
- HeapIncreaseKey(v,9,15);//p82圖
- for_each(v.begin()+1,v.end(),print);
- cout << endl << endl;
- cout << "提取個" << endl;
- cout << "max = " << HeapExtractMax(v) << endl;
- for_each(v.begin()+1,v.end(),print);
- cout << endl << endl ;
- cout << "再提取個" << endl;
- cout << "max = " << HeapExtractMax(v) << endl;
- for_each(v.begin()+1,v.end(),print);
- cout << endl << endl;
- cout << "插入個" << endl;
- MaxHeapInsert(v,20);
- for_each(v.begin()+1,v.end(),print);
- cout << endl << endl;
- return 0;
- }
程序各部分的說明在源代碼中,添加說明如下:
1、 爲了更接近僞代碼,我們將vector的0位置不用,於是left[i]=2*i,right[i]=2*i+1;
2、雖然我們的初始數組已經符合堆概念,不過這只是巧合,對於任意數組,我們應該首先對其建堆,BuildHeap
看起來,第二步插入,只是如書82頁的圖,對優先級進行了改變,而第五步的插入數,則更像是新到一個作業,很像作業調度吧?哈哈,堆,想不到也是高級貨。。。
抄書上一句話,一個堆,可以在O(lgn)時間內,支持大小爲n的集合上的任意優先隊列操作。
看到MAX-HEAP-INSERT過程,有沒有很眼熟?根據思考題6.1,其實我們建堆的時候,可以用MaxHeapInsert過程,不夠這樣建堆,感覺跟插入排序沒什麼兩樣了。
過程如下:
- void BuildMaxHeap(vector<int> &v)
- {
- v.clear();
- for (int i=0 ; i<v.size() ; i++)
- MaxHeapInsert(A,v[i]);
- }
第六章的一些想法:
關於堆排序,個人覺得, 其實也是類似選擇排序,每次選出最大的,只是比較都是每個子,左右三個節點進行,排序中規模會減少,雖然這個與選擇是一樣,不過堆引入遞歸(插入也有遞歸,其實也快不了多少,所以堆排序快的因素不是遞歸),而且堆有劃分的想法,對每個子堆分別進行。如同快排的劃分,使得上下半部分不用進行比較,從而與選擇排序比大大減少了比較次數。
關於優先級隊列,以前知道隊列調度,雖然可以用隊列進行調度,不過藉助堆這樣的結構去組織,清晰的畫出圖之後,發現理解會更深刻一點,也更形象。
菜鳥goes on ~~~