1 / 54

Main Index

1. Main Index. Contents. Lecture 6 – Queues and Priority Queues. Model for a Queue The queue ADT (STL) Queue based on array (Bounded Queue) Queue based on LinkedList Queue based on deque Radix Sort Priority Queue Priority Queue based on heap. 2. Main Index. Contents.

spence
Télécharger la présentation

Main Index

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 1 Main Index Contents Lecture 6 – Queues and Priority Queues • Model for a Queue • The queue ADT (STL) • Queue based on array (Bounded Queue) • Queue based on LinkedList • Queue based on deque • Radix Sort • Priority Queue • Priority Queue based on heap

  2. 2 Main Index Contents Grocery Store Checkout: A Model for a Queue

  3. 3 Main Index Contents The Queue A Queue is a FIFO (First in First Out) Data Structure. Elements are inserted in the Rear of the queue and are removed at the Front.

  4. 4 Main Index Contents The Queue 队列的重要应用: 1.操作系统中输入/输出缓冲   包括键盘缓冲、打印缓冲、外存设备缓冲 2.操作系统中CPU调度(多任务) CPU调度(时间片轮转法,优先队列法) 栈的重要应用: 1.中断向量表,支持系统中断调用、返回 2.中缀后缀转换

  5. Queue 实现 1、Queue 基于数组实现   空间局限   (不同于栈,栈只是一个方向增删,空间没有浪    费,而队列是双向增删,有可能导致空间浪    费,所以提出循环队列) 2、Queue 基于链表实现   空间不受限制,但需链表头、尾两个指针   (不同于栈,栈只需要链表头指针即可,因为增    删都在链表头部进行) 3、Queue 基于动态数组实现   空间不受限制,但在队头删除元素影响效率   (不同于栈,栈只是在尾部增删)

  6. Queue 实现 1、Queue 基于数组实现   数组空间声明,队头、队尾下标指针,size; 2、Queue 基于链表实现   指向队头、队尾的两个指针,size; 3、Queue 基于动态数组实现   若直接使用向量vector,则缺乏在头部的操作;   可直接使用deque容器(container) deque声明   (无需再考虑队头、队尾的位置,因为deque中有push_back(),push_front(),pop_back(),pop_front()操作,可以直接使用,利用size函数获取队列中的元素个数) http://msdn.microsoft.com/library

  7. Queue 实现 STL/CLR Library deque (STL/CLR) deque::assign (STL/CLR) deque::at (STL/CLR) deque::back (STL/CLR) deque::back_item (STL/CLR) deque::begin (STL/CLR) deque::clear (STL/CLR) deque::const_reference deque::deque (STL/CLR) deque::empty (STL/CLR) deque::end (STL/CLR) deque::erase (STL/CLR) deque::front (STL/CLR) deque::insert (STL/CLR) deque::iterator (STL/CLR) deque::operator!= (STL/CLR) deque::operator[] (STL/CLR) deque::pop_back (STL/CLR) deque::pop_front (STL/CLR) deque::push_back (STL/CLR) deque::push_front (STL/CLR) deque::rbegin (STL/CLR) deque::reference (STL/CLR) deque::rend (STL/CLR) deque::resize (STL/CLR) deque::size (STL/CLR) deque::swap (STL/CLR) deque::to_array (STL/CLR) deque::value_type (STL/CLR) operator< (deque) (STL/CLR) operator<= (deque) (STL/CLR) operator= (deque) (STL/CLR) operator== (deque) (STL/CLR) operator> (deque)

  8. 8 Main Index Contents The Bounded queue

  9. Bqueue Class template <typename T> class bqueue { public: bqueue(); void push(const T& item); void pop(); T& front(); const T& front() const; int size() const; bool empty() const; bool full() const; private: T queueArray[MAXQSIZE]; int qfront, qback; //qfront指向第一个有效元素 int count; //qback指向尾部最后一个元素的 }; //下一空位

  10. Bqueue Class template <typename T> bqueue<T>::bqueue(): qfront(0), qback(0), count(0) {} template <typename T> void bqueue<T>::push(const T& item) { if (count != MAXQSIZE) queueArray[qback] = item; else throw underflowError("bqueue push(): full queue"); qback = (qback+1) % MAXQSIZE; count++; } template <typename T> void bqueue<T>::pop() { if (count == 0)throw underflowError("bqueue pop(): empty queue"); qfront = (qfront+1) % MAXQSIZE; count--; }

  11. Bqueue Class template <typename T> T& bqueue<T>::front() { if (count == 0)throw underflowError("bqueue front(): empty queue"); return queueArray[qfront]; } template <typename T> const T& bqueue<T>::front() const { if (count == 0)throw underflowError("bqueue front(): empty queue"); return queueArray[qfront]; } template <typename T> int bqueue<T>::size() const { return count; }

  12. Bqueue Class template <typename T> bool bqueue<T>::empty() const { return count == 0; } template <typename T> bool bqueue<T>::full() const { return count == MAXQSIZE; }

  13. MiniQueue Class-based on linkedlist template <typename T> class miniQueue { public: miniQueue(); void push(const T& item); void pop(); T& front(); const T& front() const; int size() const; bool empty() const; private: node<T> *qfront,*qback; int count; };

  14. MiniQueue Class template <typename T> miniQueue<T>::miniQueue():qfront(NULL), qback(NULL), count(0) {} template <typename T> void miniQueue<T>::push(const T& item) { node<T> *newNode=new node<int>(item, NULL); if(qfront==NULL){ qfront=newNode; qback=newNode; } else{ qback->next=newNode; qback=newNode; } count++; }

  15. MiniQueue Class void miniQueue<T>::pop() { if (minuQueue.size() == 0) throw underflowError("miniQueue pop(): empty queue"); node<T> *tmp=qfront; qfront=qfront->next; delete tmp; count--; } template <typename T> T& miniQueue<T>::front() { if (miniQueue.size() == 0) throw underflowError("miniQueue front(): empty queue"); return qfront->nodeValue; }

  16. MiniQueue Class template <typename T> T& miniQueue<T>::back() { if (miniQueue.size() == 0) throw underflowError("miniQueue back(): empty queue"); return qback->nodeValue; } template <typename T> int miniQueue<T>::size() const { return count; } template <typename T> bool miniQueue<T>::empty() const { return count==0; }

  17. deQueue Class-based on deque Include<deque> Using namespace std; template <typename T> class deQueue { public: deQueue(); void push(const T& item); void pop(); T& front(); const T& front() const; int size() const; bool empty() const; private: deque<T> dqueue; };

  18. deQueue Class-based on deque template <typename T> deQueue<T>::deQueue() {} template <typename T> void deQueue<T>::push(const T& item) { dqueue.push_back(item); } void deQueue<T>::pop() { if (dqueue.size() == 0) throw underflowError("miniQueue pop(): empty queue"); dqueue.pop_front(); }

  19. deQueue Class-based on deque template <typename T> T& deQueue<T>::front() { if (dqueue.size() == 0) throw underflowError("miniQueue front(): empty queue"); return dqueue.front(); } template <typename T> const T& deQueue<T>::front() const { if (dqueue.size() == 0) throw underflowError("miniQueue front(): empty queue"); return dqueue.front(); }

  20. deQueue Class-based on deque template <typename T> T& deQueue<T>::back() { if (dqueue.size() == 0) throw underflowError("miniQueue back(): empty queue"); return dqueue.back(); } template <typename T> const T& deQueue<T>::back() const { if (dqueue.size() == 0) throw underflowError("miniQueue back(): empty queue"); return dqueue.back(); }

  21. deQueue Class-based on deque template <typename T> int deQueue<T>::size() const { return dqueue.size(); } template <typename T> bool deQueue<T>::empty() const { return dqueue.empty(); }

  22. STL Queue Class* adapter container(适配器容器) Stack: 一般使用vector实现,也可使用双端队列deque实现,deque在STL中定义为类似双端向量的顺序容器(参见STL),即可以在向量的头、尾进行插入和删除,push_front, push_front, pop_back, pop_back;也可使用数组。 Queue:一般使用list实现,也可使用双端队列deque实现,使用pop_front和push_back。也可使用数组实现。 For example: Queue<int, list<int>>qList; Queue<int, deque<int>>qDeque;

  23. STL Queue Class* queue<int, list<int>>qList; queue<int, deque<int>>qDeque; int value; Cout<<“Enter an integer >0 or 0 to quit:”; Cin>>value; While(value!=0) { if(value%2==0)qList.push(value); else qDeque.push(value); Cout<<“Enter an integer >0 or 0 to quit:”; Cin>>value; } Cout<<endl<<“Even numbers:”;

  24. STL Queue Class* While(!qList.empty()) { cout<<qList.front()<< “ “; qList.pop(); } Cout<<endl<<endl; Cout<<“Odd numbers:”; While(!qDeque.empty()) { cout<<qDeque.front()<< “ “; qDeque.pop(); } Cout<<endl;

  25. queue(); Create an empty queue. CLASS queue CLASS queue <queue> <queue> Constructor Operations bool empty() const; Check whether the queue is empty. Return true if it is empty and false otherwise. T&l front(); Return a reference to the value of the item at the font of the queue. Precondition: The queue is not empty. 25 Main Index Contents

  26. const T& front() const; Constant version of front(). CLASS queue <queue> Operations void pop(); Remove the item from the front of the queue. Precondition: The queue is not empty. Postcondition: The element at the front of the queue is the element that was added immediately after the element just popped or the queue is empty. 26 Main Index Contents

  27. void push(const T& item); Insert the argument item at the back of the queue. Postcondition: The queue has a new item at the back CLASS queue <queue> Operations int size() const; Return the number of elements in the queue. 27 Main Index Contents

  28. CLASS stack CLASS stack <stack> <stack> Constructor Operations stack(); Create an empty stack bool empty(); const Check whether the stack is empty. Return true if it is empty and false otherwise. 28 Main Index Contents

  29. CLASS stack <stack> Operations void pop(); Remove the item from the top of the stack. Precondition: The stack is not empty. Postcondition: Either the stack is empty or the stack has a new topmost item from a previous push. void push(const T& item); Insert the argument item at the top of the stack. Postcondition: The stack has a new item at the top. 29 Main Index Contents

  30. CLASS stack <stack> Operations int size() const; Return the number of items on the stack. T& top() const; Return a reference to the value of the item at the top of the stack. Precondition: The stack is not empty. const T& top() const; Constant version of top(). 30 Main Index Contents

  31. 31 Main Index Contents The Radix Sort Order ten 2 digit numbers in 10 bins from smallest number to largest number. Requires 2 calls to the sort Algorithm. Initial Sequence: 91 6 85 15 92 35 30 22 39 Pass 0: Distribute the cards into bins according to the 1's digit (100).

  32. 32 Main Index Contents The Radix Sort Final Sequence: 30 91 92 22 85 15 35 6 39 Pass 1: Take the new sequence and distribute the cards into bins determined by the 10's digit (101).

  33. Radix Sort void distribute(const vector<int>& v, queue<int> digitQueue[], int power) { int i; for (i = 0; i < v.size(); i++) digitQueue[(v[i] / power) % 10].push(v[i]); } void collect(queue<int> digitQueue[], vector<int>& v) { int i = 0, digit; for (digit = 0; digit < 10; digit++) while (!digitQueue[digit].empty()) { v[i] = digitQueue[digit].front(); digitQueue[digit].pop(); i++; } }

  34. Radix Sort void radixSort(vector<int>& v, int d) { int i; int power = 1; queue<int> digitQueue[10]; for (i=0;i < d;i++) { distribute(v, digitQueue, power); collect(digitQueue, v); power *= 10; } }

  35. Radix Sort #include <iostream> #include <iomanip> #include <vector> #include "d_random.h" #include "d_sort.h" using namespace std; void displayVector(const vector<int>& v); int main() { vector<int> intVector; randomNumber rnd; int i; for (i = 0; i < 50; i++) intVector.push_back(rnd.random(100000)); radixSort(intVector, 5); displayVector(intVector); return 0; }

  36. Radix Sort void displayVector(const vector<int>& v) { int i; for (i=0; i < v.size(); i++) { cout << setw(12) << v[i]; if ((i+1) % 6 == 0) cout << endl; } cout << endl; }

  37. 离散事件动态模拟 模拟免费电话服务中心主要工作流程: 1.模拟工作时间段的来电情况;   通过时间递减,来模拟每分钟可能发生的事件; 2.在每个时刻,检查当前电话是否完成:   若完成,将其从电话队列中删除,取下一个等待电话;   若未完成,不作操作; 2.同时,检查当前时间是否有电话拨入;   若有电话拨入,记录其到达时间,并随机产生服务时间,    将其排入电话等待队列;   若没有,不作操作;

  38. 离散事件动态模拟 模拟免费电话服务中心解决方案: 1.设定模拟时间,通过时间递减直止为0来模拟; 2.设置电话到达频率myArrivalRate; 3.设置电话的随机服务时间,可由用户指定 如1,2,3,4,5服务分钟所占百分比为:50,25,15,7,3   可用数组实现。 4.设计类call,描述电话拨入和服务时间; 5.设计类timer,描述模拟时间的设定和递减; 6.使用已有类queue,保存电话队列; 7.设计类simulation;

  39. 离散事件动态模拟 Simulation初始化流程: myCallsReceived = 0; myTotalWaitingTime = 0; 输入 callsPerHour 每分钟电话数; 输入电话服务时间分配情况 myServicePercent[i] 初始化计时器 程序主要流程run(): 若计时器不为零 1.检查当前服务是否结束,不结束服务时间-1;   若已结束,而等待队列不为空取下一个等待电话; 2.检查是否有新电话进入,若有(概率统计) 则构造

  40. 离散事件动态模拟 Simulation::Simulation() {myCallsReceived = 0; myTotalWaitingTime = 0;int callsPerHour; cout << "Enter arrival rate (calls per hour): "; cin >> callsPerHour; myArrivalRate = callsPerHour / 60.0; // convert to calls per minute cout << "Enter percent of calls serviced in\n"; int percent, sum = 0; for (int i = 0; i < NUM_CATEGORIES - 1; i++) { cout << " <= " << i + 1 << " min. "; cin >> percent; sum += percent; myServicePercent[i] = sum; }//初始化电话服务时间(1,2,3,4,5,分钟)的概率 myServicePercent[NUM_CATEGORIES - 1] = 100; cout << "Enter # of minutes to run simulation: "; cin >> myLengthOfSimulation; myTimer.set(myLengthOfSimulation); long seed = long(time(0)); // seed for random number generator srand(seed); }

  41. 离散事件动态模拟 void Simulation::run() { int busyTimeRemaining = 0; while (myTimer.timeRemaining() > 0) { service(busyTimeRemaining); checkForNewCall(); myTimer.tick(); } cout << "\nNot accepting more calls -- service those waiting\n"; while (!myIncomingCalls.empty()) { service(busyTimeRemaining); myTimer.tick(); } display(cout); }

  42. 离散事件动态模拟 Timer::Timer(int initTime) { assert(initTime >= 0); myMinutes = initTime; } void Timer::set(int minutes) { assert(minutes >= 0); myMinutes = minutes; } void Timer::tick() { myMinutes--; } int Timer::timeRemaining() const { return myMinutes; }

  43. 离散事件动态模拟 void Simulation::service(int & busyTimeRemaining) { if (busyTimeRemaining > 0) // servicing a call当前电话服务 busyTimeRemaining--; // service it for another minute else if (!myIncomingCalls.empty()) // calls are waiting 有等待电话 { Call nextCall = myIncomingCalls.front(); myIncomingCalls.dequeue(); busyTimeRemaining = nextCall.getServiceTime(); myTotalWaitingTime += nextCall.getArrivalTime() - myTimer.timeRemaining(); } }

  44. 离散事件动态模拟 void Simulation::checkForNewCall() { int x = rand() % 100; if (x < 100 * myArrivalRate) {int r = rand() % 100; int serviceTime = 0; while (r > myServicePercent[serviceTime]) serviceTime++; //确定服务时间 Call newCall(myTimer, serviceTime + 1); myIncomingCalls.enqueue(newCall); myCallsReceived++; } }

  45. 离散事件动态模拟 Call::Call() { myTimeOfArrival = myServiceTime = 0; } Call::Call(const Timer & t, int serviceTime) { myTimeOfArrival = t.timeRemaining(); myServiceTime = serviceTime; } int Call::getArrivalTime() const { return myTimeOfArrival;} int Call::getServiceTime() const { return myServiceTime; } void Call::display(ostream & out) const { out << "Arrival Time: " << myTimeOfArrival << endl << "Service Time: " << myServiceTime << endl; } ostream & operator<<(ostream & out, const Call & aCall) { aCall.display(out); return out; }

  46. Priority Queue A Special form of queue from which items are removed according to their designated priority and not the order in which they entered. Items entered the queue in sequential order but will be removed in the order #2, #1, #4, #3.

  47. priority_queue(); Create an empty priority queue. Type T must implement the operator <. CLASS priority_queue CLASS priority_queue <queue> <queue> Constructor Operations bool empty() const; Check whether the priority queue is empty. Return true if it is empty, and false otherwise. Create void pop(); Remove the item of highest priority from the queue. Precondition: The priority queue is not empty. Postcondition: The priority queue has 1 less element 47 Main Index Contents

  48. CLASS priority_queue <queue> Operations 48 Main Index Contents void push(const T& item); Insert the argument item into the priority queue. Postcondition: The priority queue contains a new element. int size() const; Return the number of items in the priority queue. T& top(); Return a reference to the item having the highest priority. Precondition: The priority queue is not empty. const T& top(); Constant version of top().

  49. 优先队列的实现 1.使用数组实现 2.使用链表实现 3.使用deque实现? 4.使用堆(heap)实现

  50. 优先队列的实现(STL) STL中默认的是最大优先队列,声明 priority_queue<int> q 即 priority_queue<int, vector<int>, less<int> > less默认为最大优先队列; 如果需要最小优先队列,可声明priority_queue<int,vector<int>, greater<int>>q; 注:若优先队列中的数据为用户自定义类,也可通过重载运算“<”来实现最大、最小优先级的改变。 priority_queue<int, vector<int>, less<int> > ipq; priority_queue<int, vector<int>, greater<int> > gipq; priority_queue<int, vector<int> > pq; priority_queue<int > intpq;

More Related