《算法导论》学习摘要chapter-6——优先队列

来源:互联网 发布:杭州和盈培训java学费 编辑:程序博客网 时间:2024/05/21 07:47

            本章堆排序内容是《算法导论》教材第二部分《排序与顺序统计量》的第一讲堆排序中的堆排序应用。博客参考部分已经在相应位置标记出

一、优先队列回顾

         优先队列:和数据结构中提到的队列不同的是,优先队列更加注重“优先级”三个字。队列具有FIFO原则,但有些应用场合队列的特性并不能满足系统的执行要求,效率太低,这就促使优先队列的产生。比如在系统进程调度中,若根据FIFO原则,一个大进程执行的时间长,消耗资源大;小进程执行时间短,占用资源少。当一个大进程先于一个小进程生成时,在单处理器环境下,小进程就需要等待较长的时间才能被调度执行。这种情况不利用计算机的推广,不是用户想看到的情况。

         所以,利用队列来调度进行的策略就显得很“愚蠢”,但队列的独有特性又符合计算机运行的原理。所以就需要对队列进行改进,所以在队列的基础上又设计出优先队列。

        我查了有关优先队列的标准定义:优先队列 是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。优先队列是0个或多个元素的集合,每个元素都有一个优先权或值。优先权队列中的元素可以有相同的优先权,查找与删除操作可根据任意优先权进行。

         使用优先队列,首先要包函STL头文件“queue”。当然了,在初学阶段,我们可以自己来设计一个优先队列类,以便深入了解有优先队列的具体实现过程(见示例代码部分)。

二、依据堆结构的优先队列

        下面我们将介绍《算法导论》课本的优先队列部分。
        优先队列和堆一样,也有两种主要形式:最大优先队列和最小优先队列。这里我们主要关心最大优先队列。
        优先队列priority queue)是一种用来维护由一组元素构成的集合S的数据结构,其中的每一个元素都有一个相关的值,称为关键字。一个最大优先队列支持以下四种操作:

INSERT(S,x):把元素x插入到集合S中;

MAXIMUM(S):返回S中具有最大键值的元素;

EXTRACT-MAX(S):去掉并返回S中的具有最大关键字的元素;

INCREASE-KEY(S,x,key):将元素x的关键字值增加到key,这里key值不小于x的原关键字的值。

    下面将分别介绍这四种操作的具体实现。

2.1 MAXIMUM(S)操作
        程序HEAP_MAXIMUM用O(1)时间实现MAXIMUM(S)操作:返回最大堆第一个元素的值即可。

        MAXIMUM(S)操作伪代码:

HEAP-MAXIMUM(A)1   return A[1]

2.2 EXTRACT-MAX(S)操作
        程序HEAP-EXTRACT-MAX实现EXTRACT_MAX操作:删除最大堆中第一个元素,然后调整堆
        EXTRACT-MAX(S)操作过程如下:首先将堆中最后一个元素复制到第一个位置,然后将堆的大小减1(实现删除最后一个元素,最后,从第一个节点位置开始调整堆,直到满足最大堆性质位置。
        EXTRACT-MAX(S)操作伪代码如下:

HEAP-EXTRACT-MAX(A)1   if heap-size[A] < 12      then error  “heap underflow”3   max <----- A[1]4   A[1] <----- A[heap-size]5   heap-size[A] <----- heap-size[A] - 16   MAX-HEAPIFY(A , 1)7   return max
     下图是HEAP-EXTRACT-MAX(A)操作的一个示例:
               


2.3 INCREASE-KEY(S,x,key)操作

         HEAP-INCREASE-KEY(S,x,key):将元素x的关键字值增加到key,通过下标来标识要增加的元素的优先级key,增加元素后需要调整堆。
         HEAP-INCREASE-KEY(S,x,key)操作首先将元素A[i]的关键字更新为新的值。更新后A[i]的关键值可能会破坏最大堆的性质,所以更新后还需要调整堆,在调整的过程中,该元素不断与其父结点关键字相比较,如果该元素的关键字较大,则交换它们的关键字并继续调整;当元素的关键字小于其父母时,调整终止。
        INCREASE-KEY(S,x,key)操作伪代码如下:

HEAP-INCREASE-KEY(S,x,key)1   if key < A[i]2       then error “new key is smaller than current key”3   A[i] <----- key4   while i > 1 and A[ PARENT[i] < A[i] ]5        do exchange A[i] <-----> A[PARENT(i)]6          i <----- PARENT(i)
        下图是INCREASE-KEY(S,x,key)操作的一个示例:

               



2.4 INSERT(S,x)操作
          该操作是向最大堆中插入新的关键字x。插入操作满足队列的插入在尾部的原则,所以在该插入操作中,新的关键字将被安置在优先级的队尾部,然后从尾部的父节点开始自顶向上调整,使其满足堆的性质

         INSERT(S,x)操作的伪代码如下:

MAX-HEAP-INSERT(A,key)1    heap-size[A] <------ heap-size[A] +12    A[heap-size[A]] <------ -00(负无穷)3    HEAP-INCREASE-KEY( A, heap-size[A], key).

三、代码部分

3.1  队列
       代码参考资料:http://www.cnblogs.com/heqinghui/archive/2013/07/30/3225407.html
#include <iostream>#include <functional>  #include <queue>  #include <vector>  using namespace std;//定义结构,使用运算符重载,自定义优先级1  struct cmp1{bool operator ()(int &a, int &b){return a>b;//最小值优先  }};struct cmp2{bool operator ()(int &a, int &b){return a<b;//最大值优先  }};//定义结构,使用运算符重载,自定义优先级2  struct number1{int x;bool operator < (const number1 &a) const {return x>a.x;//最小值优先  }};struct number2{int x;bool operator < (const number2 &a) const {return x<a.x;//最大值优先  }};int a[] = { 14, 10, 56, 7, 83, 22, 36, 91, 3, 47, 72, 0 };number1 num1[] = { 14, 10, 56, 7, 83, 22, 36, 91, 3, 47, 72, 0 };number2 num2[] = { 14, 10, 56, 7, 83, 22, 36, 91, 3, 47, 72, 0 };int main(){priority_queue<int>que;//采用默认优先级构造队列  priority_queue<int, vector<int>, cmp1>que1;//最小值优先  priority_queue<int, vector<int>, cmp2>que2;//最大值优先  priority_queue<int, vector<int>, greater<int> >que3;//最大值优先  priority_queue<int, vector<int>, less<int> >que4;//最小值优先  priority_queue<number1>que5;priority_queue<number2>que6;for(int i = 0; a[i]!=NULL; i++){que.push(a[i]);que1.push(a[i]);que2.push(a[i]);que3.push(a[i]);que4.push(a[i]);}for(int i = 0; num1[i].x!=NULL; i++)que5.push(num1[i]);for(int i = 0; num2[i].x!=NULL; i++)que6.push(num2[i]);cout<<"采用默认优先关系:\n(priority_queue<int>que;)\n";cout<<"Queue 0:\n";while (!que.empty()){printf("%3d", que.top());que.pop();}cout << endl<<endl;cout<<"采用结构体自定义优先级方式一:\n(priority_queue<int,vector<int>,cmp>que;)\n";cout<<"Queue 1:\n";while (!que1.empty()){printf("%3d", que1.top());que1.pop();}cout << endl;cout<<"Queue 2:\n";while (!que2.empty()){printf("%3d", que2.top());que2.pop();}cout << endl << endl;cout<<"采用头文件\"functional\"内定义优先级:\n(priority_queue<int,vector<int>,greater<int>/less<int> >que;)\n";cout<<"Queue 3:\n";while (!que3.empty()){printf("%3d", que3.top());que3.pop();}cout << endl;cout<<"Queue 4:\n";while (!que4.empty()){printf("%3d", que4.top());que4.pop();}cout << endl<<endl;cout<<"采用结构体自定义优先级方式二:\n(priority_queue<number>que)\n";cout<<"Queue 5:\n";while (!que5.empty()){printf("%3d", que5.top());que5.pop();}cout << endl;cout<<"Queue 6:\n";while (!que6.empty()){printf("%3d", que6.top());que6.pop();}cout << endl << endl;system("pause");return 0;}
运行结果:
               

3.2 优先级队列
        优先级队列中有多个事件发生,每个事件有自己独立的优先级,优先级是非负数,数值越大优先级越高。采用最大优先级队列模拟事件执行的优先顺序。具体操作包括:
  1. 向优先级队列中添加一个新事件;
  2. 获取优先级队列中优先级最高的事件;
  3. 删除优先级队列中指定位置的事件;
  4. 增加优先级队列中指定位置事件的优先级;
  5. 降低优先级队列中指定位置事件的优先级
     说明,下面代码很不错,对理解优先队列很有帮助,代码出自:http://www.cnblogs.com/Anker/archive/2013/01/23/2873951.html
#include <iostream>#include <string>#include <cstdlib>using namespace std;const static int QUEUELEN = 100;class Event{public:Event() :eventname(""), priority(-1){};Event(const string &en, const int p) :eventname(en), priority(p){};Event(const Event& en){eventname = en.eventname;priority = en.priority;}~Event(){};int get_event_priority()const{return priority;}string get_event_name()const{return eventname;}void increase_event_priority(const int k){priority = priority + k;}void decrease_event_priority(const int k){priority = priority - k;}void show_event() const{cout << "Eventname is: (" << eventname << ") and the priority is: " << priority << endl;}private:string eventname;int priority;};class PriorityQueue{public:PriorityQueue();void adjust_event(int index);Event get_event()const;void insert_event(const Event& en);void increase_event_priority(int pos, int k);Event delete_event(int pos);void show_events() const;~PriorityQueue();private:Event *events;int length;};PriorityQueue::PriorityQueue(){events = new Event[QUEUELEN];length = 0;}PriorityQueue::~PriorityQueue(){if (!events)delete[] events;length = 0;}//adjust max heap void PriorityQueue::adjust_event(int index){int left, right, largest;Event temp;while (1){left = index * 2;right = index * 2 + 1;if (left <= length &&events[left].get_event_priority() > events[index].get_event_priority())largest = left;elselargest = index;if (right <= length &&events[right].get_event_priority() > events[largest].get_event_priority())largest = right;if (largest != index){temp = events[index];events[index] = events[largest];events[largest] = temp;index = largest;}elsebreak;}}Event PriorityQueue::get_event()const{if (length != 0)return events[1];elsereturn Event();}void PriorityQueue::insert_event(const Event& en){length = length + 1;events[length] = en;increase_event_priority(length, 0);}void PriorityQueue::increase_event_priority(int pos, int k){int i, parent;Event temp;if (pos > length){cout << "error: the pos index is larger than queue length" << endl;return;}events[pos].increase_event_priority(k);i = pos;parent = i / 2;while (i>1&& events[parent].get_event_priority() < events[i].get_event_priority()){temp = events[i];events[i] = events[parent];events[parent] = temp;i = parent;parent = i / 2;}}Event PriorityQueue::delete_event(int pos){Event reten;if (pos > length){cout << "Error:pos index is larger than queue length" << endl;return reten;}reten = events[pos];events[pos] = events[length];length--;adjust_event(pos);return reten;}void PriorityQueue::show_events() const{if (length == 0){cout << "There is no any event in the priority queue" << endl;}else{cout << "There are " << length << " events in the priority queue." << endl;for (int i = 1; i <= length; i++){events[i].show_event();}}}int main(){PriorityQueue pqueue;Event en;Event en1("fork", 2);Event en2("exec", 3);Event en3("wait", 1);Event en4("signal", 6);Event en5("pthread_create", 5);pqueue.insert_event(en1);pqueue.insert_event(en2);pqueue.insert_event(en3);pqueue.insert_event(en4);pqueue.insert_event(en5);pqueue.show_events();cout << "\nThe max priority event is: " << endl;en = pqueue.get_event();en.show_event();cout << "\nIncrese event3 by 7" << endl;pqueue.increase_event_priority(3, 7);en = pqueue.get_event();en.show_event();pqueue.show_events();cout << "\nDelete the first event:" << endl;pqueue.delete_event(1);pqueue.show_events();system("pause");return 0;}
运行结果:

                



0 0
原创粉丝点击