220 likes | 419 Views
DCO 20105 Data structures and algorithms. Lecture 11: Queue & Priority Queue Basic operations of a queue Applications of a queue Priority queue and the STL’s priority queue -- By Rossella Lau. A. B. C. B. C. Queue. Queue is an ordered list of items, ordered in the input sequence
E N D
DCO20105 Data structures and algorithms • Lecture 11: Queue & Priority Queue • Basic operations of a queue • Applications of a queue • Priority queue and the STL’s priority queue -- By Rossella Lau
A B C B C Queue • Queue is an ordered list of items, ordered in the input sequence • Basically, items • are deleted at one end (the front/head of the queue) and • added at the other end (the rear/tail of the queue) • An example: The original queue D Take an item Add an item
Operations of a queue • Basic: • push() – to add an item; formerly called enqueue() • pop() – to remove an item; formerly called dequeue() • Assistance: • size() – returns the number of items in a queue • empty() – to check if a queue is empty • front() – returns the first element of a queue
Exercises • Ford’s 8:9 queue<int> q; int x = 5, y = 3; q.push(8); q.push(9); q.push(y); X = q.fron(); q.pop(); q.push(18); x = q.front(); q.push(22); while (!q.empty()) { y = q.front(); q.pop(); cout << y << “ “; } cout << x << endl; • Ford’s 8:10: List the elements in intQ after each of the following operations: queue<int> intQ; intQ.push(18); intQ.push(2); intQ.push(intQ.front()); intQ.push(intQ.front()); intQ.pop();
Typical applications • A real life application – check out queues in a super market (Ford’s slide: 8.2) • When a customer goes to a cashier – push() • If there is a cashier available, check out at that cashier • Line up a queue at the end and wait for checking out • When a cashier is working – pop() • Perform check out for the first customer on her/his line one by one
Services for others • As a service for other data structures and algorithms • Radix sort • Traverse a binary tree in a breadth first order; i.e., from top to bottom and at each level, from left to right
0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 Re-visit the Radix sort 25 57 48 37 12 92 86 33 12 25 12 92 33 25 86 57 37 48 12 92 33 37 for (i=0;i<10,i++) while (!qs[i].empty()) qs[i].pop(); 33 48 57 25 86 57 37 86 48 92 12 25 33 37 48 57 86 92 push(ni) to qs[k]
92 37 86 33 12 48 57 25 Breadth First Search (BFS) order • A BT’s Breadth First Search order is similar to the implicit array index • E.g., The BFS order for the BT on the right hand side is: 92, 37, 86, 33, 12, 48, 57, 25
#include <queue> …… void bfs(void) const { queue <BSTNode<T> *> children; children.push(root); while (! children.empty()) { if (children.front()->left) children.push(children.front()->left); if (children.front()->right) children.push(children.front()->right); cout << children.front()->getItem() << " "; children.pop(); } cout << endl; } BFS traversal
Implementation of a queue When using a vector: • As elements grow (shift) in one direction, slots in the beginning become useless while new elements may be required to re-size the array frequently • Another approach is to use an array in a cyclic method -- calculation of the index becomes a bit more complicated and care should be taken in how to determine the front and the rear of the queue and an empty queue
front rear A B C 0 1 2 3 4 front rear front front rear rear B C B C D C D 0 1 2 3 4 0 1 2 0 3 1 4 2 3 4 rear front rear front rear front C D E F C D E F D E 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 Using a cyclic vector for implementing queue Initial: pop(): push(): pop(): push(): push(): pop():
front rear 0 1 2 3 4 Initial or empty: front rear front rear A single element: 0 1 2 3 4 0 1 2 3 4 Test of empty() • When front points to the first element of a queue, it is difficult to test if a queue is empty or has a single element
front rear front rear front rear B C B C D C D 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 rear front rear front rear front C D E F C D E F D E 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 Modification of front A special way is to make the front point to the vector index immediately preceding the first element. pop(): push(): pop(): push(): push(): pop():
list-based queue • Seems a more natural way to implement queue • But the cost of the operation new/delete makes a list-based container not favorable
Implementation of a queue using a list // Queue.h template<class T> class Queue { private: list<T> queue; public: T const & front() const { return queue.front();} void push(T const & item) {queue.push_back(item);} T & pop() {T t(front()); queue.pop_front(); return t;} size_t size() const { return queue.size();} bool empty() const { return queue.empty();} };
Execution time for operations of a queue • No matter which basic container is used to build a queue, • a push() is actually a push_back() • a pop() is similar to a pop_front() • Although pop_front() is not allowed in a STL’s vector, it can use a self-defined index to remember its head and move it forward to represent a pop() operation • It can also use deque<T> • Both operations are at O(1) • Operations of a STL’s queue: Ford’s slides: 8.4-6
Priority Queue • Many applications need elements to queue up with priority. • Queues in bank: general a/c holders, priority a/c holders • Task queues: jobs assigning a higher priority can be executed earlier
Exercises • Ford’s 8:15 priority_queue<int> pq; int arr[] = {10,50,30,40,60}; int i, x, y; for (i=0; i< 5; i++) pq.push(arr[i]); pq.push(25); x = pq.top(); pq.pop(); pq.push(35); y = pq.top(); pq.pop(); cout << x << “ “ << y << endl; while (!pq.empty()) { cout << pq.top() << “ “; pq.pop(); } cout << endl; • Ford’s 8:16: priority_queue<int> intPQ; intPQ.push(5); intPQ.push(27); intPQ.push(25); intPQ.pop(); intPQ.push(intPQ.top()*2); intPQ.push(intPQ.top()*5); While (!intPQ.empty()) { cout<< intPQ.top() << “ “; intPQ.opp(); } cout << endl;
priority_queue<T> • The STL provides the class priority_queue • E.g., • push(taskA,5), push(taskB,5), push(taskC,8), push(taskD,2), push(taskE,5), push(taskF,8) • pop() returns (taskC, 8) • priority_queue uses a heap to insert an item • A heap works quite efficiently on vector and the STL uses a vector to implement priority_queue by default • The templated class of the priority_queue must provide the comparison operator <() for the heap construction
An example application • class task { string taskName, int priority; …} • operator< must be overloaded • bool task::operator<(task const & rhs) const { return priority < rhs.priority;} • The application: • priority_queue<task> taskQ; • …… • taskQ.push(taskObj); • …… • resultTask=taskQ.front(); taskQ.pop();
Summary • Queue can use different kinds of sequential containers with restricted operations as adaptor containers in the STL • Both the basic operations of a queue are at O(1) and make a queue one of the favored data structures being used in many other algorithms • Priority queue, in addition to the behaviors of a queue having a priority, uses a heap with a comparison method built on a vector or a deque
Reference • Ford: 8 • STL online references • http://www.sgi.com/tech/stl • http://www.cppreference.com/ -- END --