《算法导论》学习总结——第二部分2优先级队列
2011-07-23 14:34
465 查看
如堆一样,队列也有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页图为例
示范程序如下:
程序各部分的说明在源代码中,添加说明如下:
1、 为了更接近伪代码,我们将vector的0位置不用,于是left[i]=2*i,right[i]=2*i+1;
2、虽然我们的初始数组已经符合堆概念,不过这只是巧合,对于任意数组,我们应该首先对其建堆,BuildHeap
看起来,第二步插入,只是如书82页的图,对优先级进行了改变,而第五步的插入数,则更像是新到一个作业,很像作业调度吧?哈哈,堆,想不到也是高级货。。。
抄书上一句话,一个堆,可以在O(lgn)时间内,支持大小为n的集合上的任意优先队列操作。
看到MAX-HEAP-INSERT过程,有没有很眼熟?根据思考题6.1,其实我们建堆的时候,可以用MaxHeapInsert过程,不够这样建堆,感觉跟插入排序没什么两样了。
过程如下:
第六章的一些想法: 关于堆排序,个人觉得, 其实也是类似选择排序,每次选出最大的,只是比较都是每个子,左右三个节点进行,排序中规模会减少,虽然这个与选择是一样,不过堆引入递归(插入也有递归,其实也快不了多少,所以堆排序快的因素不是递归),而且堆有划分的想法,对每个子堆分别进行。如同快排的划分,使得上下半部分不用进行比较,从而与选择排序比大大减少了比较次数。 关于优先级队列,以前知道队列调度,虽然可以用队列进行调度,不过借助堆这样的结构去组织,清晰的画出图之后,发现理解会更深刻一点,也更形象。 菜鸟goes on ~~~
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 ~~~
相关文章推荐
- 《算法导论》学习总结——第二部分5基数排序、桶排序
- 《算法导论》学习总结——第二部分6中位数和顺序统计学
- 《算法导论》学习总结——第二部分4计数排序
- 《算法导论》第六章----优先级队列(代码实现+部分练习)
- 《算法导论》学习总结——第二部分1堆排序
- 《算法导论》学习总结——第二部分3快速排序
- 《算法导论》第六章----优先级队列(代码实现+部分练习)
- 《算法导论》笔记 第6章 6.5优先级队列
- 算法导论第一,第二部分总结
- 算法导论:堆排序的应用---优先级队列
- 《算法导论》学习总结——第三部分2Hash表
- 考察数据结构——第二部分:队列、堆栈和哈希表[译]
- 考察数据结构——第二部分:队列、堆栈和哈希表[译]
- 《算法导论》学习总结——第一部分
- Windows核心编程学习笔记 第二部分 完成编程任务 第7章 线程的调度 优先级 亲缘性
- RabbitMQ官方中文入门教程(PHP版) 第二部分:工作队列(Work queues)
- 考察数据结构——第二部分:队列、堆栈和哈希表[译]
- 算法导论Java实现-优先级队列(6.5章节)
- 第二部分:工作队列(Work queues)
- 《算法导论》笔记--优先级队列