Implementing Queues Eric Roberts CS 106B February 13, 2013.

Slides:



Advertisements
Similar presentations
Chapter 22 Implementing lists: linked implementations.
Advertisements

Stack & Queues COP 3502.
Data Structures Lecture 13: QUEUES Azhar Maqsood NUST Institute of Information Technology (NIIT)
Queues A waiting line that grows by adding elements to its end and shrinks by taking elements from its front Line at the grocery store Cars in traffic.
Queues.
Review of Stacks and Queues Dr. Yingwu Zhu. Our Focus Only link-list based implementation of Stack class Won’t talk about different implementations of.
Dynamic Allocation Eric Roberts CS 106B February 4, 2013.
COSC 1P03 Data Structures and Abstraction 9.1 The Queue Whenever you are asked if you can do a job, tell 'em, "Certainly, I can!" Then get busy and find.
Stacks, Queues, and Deques. 2 A stack is a last in, first out (LIFO) data structure Items are removed from a stack in the reverse order from the way they.
queues1 Queues Data structures that wait their turn.
E.G.M. Petrakislists, stacks, queues1 Stacks Stack: restricted variant of list –Elements may by inserted or deleted from only one end  LIFO lists –Top:
ADT Queue 1. What is a Queue? 2. STL Queue 3. Array Implementation of Queue 4. Linked List Implementation of Queue 5. Priority Queue.
Queues 4/14/2017 5:24 PM 5.2 Queues Queues Dr Zeinab Eid.
Copyright © 2009 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Chapter 18: Stacks And Queues.
Chapter 7 Queues. Copyright © 2004 Pearson Addison-Wesley. All rights reserved.1-2 Chapter Objectives Examine queue processing Define a queue abstract.
Copyright © 2012 Pearson Education, Inc. Chapter 18: Stacks And Queues.
Queue Overview Queue ADT Basic operations of queue
1 CSC 211 Data Structures Lecture 22 Dr. Iftikhar Azim Niaz 1.
Chapter 5 Queues Modified. Chapter Scope Queue processing Comparing queue implementations 5 - 2Java Software Structures, 4th Edition, Lewis/Chase.
Linked Lists Compiled by Dr. Mohammad Alhawarat CHAPTER 04.
Queues CS-240 & CS-341 Dick Steflik. Queues First In, First Out operation - FIFO As items are added they are chronologically ordered, items are removed.
Queues CS-240 & CS-341 Dick Steflik. Queues First In, First Out operation - FIFO As items are added they are chronologically ordered, items are removed.
Chapter 4 Linked Lists. © 2005 Pearson Addison-Wesley. All rights reserved4-2 Preliminaries Options for implementing an ADT List –Array has a fixed size.
TCSS 342, Winter 2005 Lecture Notes
Queues Cmput Lecture 19 Department of Computing Science University of Alberta ©Duane Szafron 2000 Some code in this lecture is based on code from.
1 Queues (Walls & Mirrors - Chapter 7). 2 Overview The ADT Queue Linked-List Implementation of a Queue Array Implementation of a Queue.
Stacks, Queues, and Deques
Chapter 14 Queues. First a Review Queue processing Using queues to solve problems – Optimizing customer service simulation – Ceasar ciphers – Palindrome.
EXPANDING STACKS AND QUEUES CS16: Introduction to Data Structures & Algorithms 1 Tuesday, February 10, 2015.
CSE 373 Data Structures and Algorithms Lecture 2: Queues.
1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 8 Stacks and Queues Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall.
CHAPTER 05 Compiled by: Dr. Mohammad Omar Alhawarat Stacks & Queues.
CS 1031 Queues Definition of a Queue Examples of Queues Design of a Queue Class Different Implementations of the Queue Class.
Stacks and Linked Lists. Abstract Data Types (ADTs) An ADT is an abstraction of a data structure that specifies – Data stored – Operations on the data.
DATA STRUCTURES AND ALGORITHMS Lecture Notes 4 Prepared by İnanç TAHRALI.
Copyright © 2012 Pearson Education, Inc. Chapter 18: Stacks And Queues.
1 C++ Plus Data Structures Nell Dale Chapter 4 ADTs Stack and Queue Modified from the slides by Sylvia Sorkin, Community College of Baltimore County -
1 Chapter 7 Stacks and Queues. 2 Stack ADT Recall that ADT is abstract data type, a set of data and a set of operations that act upon the data. In a stack,
Pointers OVERVIEW.
30 May Stacks (5.1) CSE 2011 Winter Stacks2 Abstract Data Types (ADTs) An abstract data type (ADT) is an abstraction of a data structure An.
09-1 Queues and List-Based ADT Implementations Problem Set: PS3 due Wednesday, March 7 Wellesley College CS230 Lecture 09 Monday, February 26 Handout #18.
IKI 10100: Data Structures & Algorithms Ruli Manurung (acknowledgments to Denny & Ade Azurat) 1 Fasilkom UI Ruli Manurung (Fasilkom UI)IKI10100: Lecture6.
Collection Classes Eric Roberts CS 106B January 14, 2013 (Part 1: Vectors, Grids, Stacks, and Queues)
Nyhoff, ADTs, Data Structures and Problem Solving with C++, Second Edition, © 2005 Pearson Education, Inc. All rights reserved Stacks.
Stacks And Queues Chapter 18.
1 Linked-list, stack and queue. 2 Outline Abstract Data Type (ADT)‏ Linked list Stack Queue.
Dynamic Array. An Array-Based Implementation - Summary Good things:  Fast, random access of elements  Very memory efficient, very little memory is required.
Review of Stacks and Queues Dr. Yingwu Zhu. How does a Stack Work? Last-in-First-out (LIFO) data structure Adding an item Push operation Removing an item.
CS 261 Fall 2009 Dynamic Array Introduction (aka Vector, ArrayList)
Queues Chapter 5 Queue Definition A queue is an ordered collection of data items such that: –Items can be removed only at one end (the front of the queue)
2005MEE Software Engineering Lecture 7 –Stacks, Queues.
Copyright © 2015, 2012, 2009 Pearson Education, Inc., Publishing as Addison-Wesley All rights reserved. Chapter 18: Stacks and Queues.
Review Array Array Elements Accessing array elements
18 Chapter Stacks and Queues
CS505 Data Structures and Algorithms
Chapter 18: Stacks and Queues.
Queues 5/11/2018 Presentation for use with the textbook Data Structures and Algorithms in Java, 6th edition, by M. T. Goodrich, R. Tamassia, and M. H.
Editor Buffers Eric Roberts CS 106B February 6, 2013.
Queue.
Queues Queues Queues.
Stack and Queue APURBO DATTA.
CMSC 341 Lecture 5 Stacks, Queues
Chapter 19: Stacks and Queues.
Queues 11/16/2018 4:18 AM Queues 11/16/2018 4:18 AM Queues.
CSC 143 Queues [Chapter 7].
Cs212: Data Structures Computer Science Department Lecture 7: Queues.
CS210- Lecture 5 Jun 9, 2005 Agenda Queues
Queues Definition of a Queue Examples of Queues
Getting queues right … finally (?)
Dynamic Array: Implementation of Stack
Presentation transcript:

Implementing Queues Eric Roberts CS 106B February 13, 2013

Outline Chapter 14 presents complete implementations for three of the ADTs you’ve been using since the second assignment: stacks, queues, and vectors. We described one implementation of the Stack class in Monday’s lecture.Chapter 14 presents complete implementations for three of the ADTs you’ve been using since the second assignment: stacks, queues, and vectors. We described one implementation of the Stack class in Monday’s lecture. The reader presents two different strategies to represent the Stack and Queue classes: one that uses an array to store the elements and one that uses a linked list. For each of these strategies, implementing a Stack turns out to be much easier.The reader presents two different strategies to represent the Stack and Queue classes: one that uses an array to store the elements and one that uses a linked list. For each of these strategies, implementing a Stack turns out to be much easier. In today’s lecture, I am going to focus on implementing the Queue class, leaving the details of implementing the Stack and Vector classes to the text.In today’s lecture, I am going to focus on implementing the Queue class, leaving the details of implementing the Stack and Vector classes to the text.

Methods in the Queue Class queue.size() Returns the number of values in the queue. queue.isEmpty() Returns true if the queue is empty. queue.enqueue(value) Adds a new value to the end of the queue (which is called its tail). queue.dequeue() Removes and returns the value at the front of the queue (which is called its head). queue.peek() Returns the value at the head of the queue without removing it. queue.clear() Removes all values from the queue.

/* * File: queue.h * * This interface defines a general queue abstraction that uses * templates so that it can work with any element type. */ #ifndef _queue_h #define _queue_h /* * Template class: Queue * * This class template models a queue, which is a linear collection * of values that resemble a waiting line. Values are added at * one end of the queue and removed from the other. The fundamental * operations are enqueue (add to the tail of the queue) and dequeue * (remove from the head of the queue). Because a queue preserves * the order of the elements, the first value enqueued is the first * value dequeued. Queues therefore operate in a first-in-first-out * (FIFO) order. For maximum generality, the Queue class is defined * using a template that allows the client to define a queue that * contains any type of value, as in Queue or Queue. */ The queue.h Interface

/* * File: queue.h * * This interface defines a general queue abstraction that uses * templates so that it can work with any element type. */ #ifndef _queue_h #define _queue_h /* * Template class: Queue * * This class template models a queue, which is a linear collection * of values that resemble a waiting line. Values are added at * one end of the queue and removed from the other. The fundamental * operations are enqueue (add to the tail of the queue) and dequeue * (remove from the head of the queue). Because a queue preserves * the order of the elements, the first value enqueued is the first * value dequeued. Queues therefore operate in a first-in-first-out * (FIFO) order. For maximum generality, the Queue class is defined * using a template that allows the client to define a queue that * contains any type of value, as in Queue or Queue. */ template class Queue { public: /* * Constructor: Queue * Usage: Queue queue; * * Initializes a new empty queue containing the specified value type. */ Queue(); /* * Destructor: ~Queue * * Deallocates any heap storage associated with this queue. */ ~Queue(); The queue.h Interface

template class Queue { public: /* * Constructor: Queue * Usage: Queue queue; * * Initializes a new empty queue containing the specified value type. */ Queue(); /* * Destructor: ~Queue * * Deallocates any heap storage associated with this queue. */ ~Queue(); /* * Method: size * Usage: int nElems = queue.size(); * * Returns the number of elements in this queue. */ int size(); /*... */ bool isEmpty(); /*... */ void clear(); /*... */ void enqueue(ValueType value); /*... */ ValueType dequeue(); /*... */ ValueType peek(); The queue.h Interface

/* * Method: size * Usage: int nElems = queue.size(); * * Returns the number of elements in this queue. */ int size(); /*... */ bool isEmpty(); /*... */ void clear(); /*... */ void enqueue(ValueType value); /*... */ ValueType dequeue(); /*... */ ValueType peek(); The queue.h Interface /* Private section */ }; /* * The template feature of C++ works correctly only if the compiler * has access to both the interface and the implementation at the * same time. As a result, the compiler must see the code for * the implementation at this point, even though that code is * not something that the client needs to see in the interface. * Using the #include facility of the C++ preprocessor allows the * compiler to have access to the code without forcing the client * to wade through the details. */ #endif Private section goes here. Implementation section goes here.

An Overly Simple Strategy The most straightforward way to represent the elements of a queue is to store the elements in an array, exactly as in the Stack class from Monday.The most straightforward way to represent the elements of a queue is to store the elements in an array, exactly as in the Stack class from Monday. Given this representation, the enqueue operation is extremely simple to implement. All you need to do is add the element to the end of the array and increment the element count. That operation runs in O(1) time.Given this representation, the enqueue operation is extremely simple to implement. All you need to do is add the element to the end of the array and increment the element count. That operation runs in O(1) time. The problem with this simplistic approach is that the dequeue operation requires removing the element from the beginning of the array. If you’re relying on the same strategy you used in the array-based editor, implementing this operation requires moving all the remaining elements to fill the hole left by the dequeued element. That operation therefore takes O(N) time.The problem with this simplistic approach is that the dequeue operation requires removing the element from the beginning of the array. If you’re relying on the same strategy you used in the array-based editor, implementing this operation requires moving all the remaining elements to fill the hole left by the dequeued element. That operation therefore takes O(N) time.

Fixing the O(N) Problem The key to fixing the problem of having dequeue take O(N) time is to eliminate the need for any data motion by keeping track of two indices: one to mark the head of the queue and another to mark the tail.The key to fixing the problem of having dequeue take O(N) time is to eliminate the need for any data motion by keeping track of two indices: one to mark the head of the queue and another to mark the tail. Given these two indices, the enqueue operation stores the new element at the position marked by the tail index and then increments tail so that the next element is enqueued into the next slot. The dequeue operation is symmetric. The next value to be dequeued appears at the array position marked by the head index. Removing it is then simply a matter of incrementing head.Given these two indices, the enqueue operation stores the new element at the position marked by the tail index and then increments tail so that the next element is enqueued into the next slot. The dequeue operation is symmetric. The next value to be dequeued appears at the array position marked by the head index. Removing it is then simply a matter of incrementing head. Unfortunately, this strategy typically ends up filling the array space even when the queue itself contains very few elements, as illustrated on the next slide.Unfortunately, this strategy typically ends up filling the array space even when the queue itself contains very few elements, as illustrated on the next slide.

0 0 8 Tracing the Array-Based Queue array capacity tail head ABCDEFG Queue queue; queue.enqueue('A') queue.enqueue('B') queue.enqueue('C') queue.enqueue('D') queue.enqueue('E') queue.enqueue('F') queue.enqueue('G') queue.enqueue('H') queue.dequeue() 'A'  queue.dequeue() 'B'  queue.dequeue() 'C'  queue.dequeue() 'D'  Consider what happens if you execute the operations shown.Consider what happens if you execute the operations shown. Each enqueue operation adds a value at the tail of the queue.Each enqueue operation adds a value at the tail of the queue. Each dequeue operation takes its result from the head.Each dequeue operation takes its result from the head. If you continue on in this way, what happens when you reach the end of the array space?If you continue on in this way, what happens when you reach the end of the array space?              queue.enqueue('I') H 8 

8 0 8 Tracing the Array-Based Queue array capacity tail head IEFG 1234 Queue queue; queue.enqueue('A') queue.enqueue('B') queue.enqueue('C') queue.enqueue('D') queue.enqueue('E') queue.enqueue('F') queue.enqueue('G') queue.enqueue('H') queue.dequeue() 'A'  queue.dequeue() 'B'  queue.dequeue() 'C'  queue.dequeue() 'D'  queue.enqueue('I') H  At this point, enqueuing the I would require expanding the array, even though the queue contains only four elements.At this point, enqueuing the I would require expanding the array, even though the queue contains only four elements. The solution to this problem is to let the elements cycle back to the beginning of the array.The solution to this problem is to let the elements cycle back to the beginning of the array. 1

Implementing the Ring-Buffer Strategy The data structure described on the preceding slide is called a ring buffer because the end of the array is linked back to the beginning.The data structure described on the preceding slide is called a ring buffer because the end of the array is linked back to the beginning. The arithmetic operations necessary to implement the ring buffer strategy are easy to code using modular arithmetic, which is simply normal arithmetic in which all values are reduced to a specific range by dividing each result by some constant (in this case, the capacity of the array) and taking the remainder. In C++, you can use the % operator to implement modular arithmetic.The arithmetic operations necessary to implement the ring buffer strategy are easy to code using modular arithmetic, which is simply normal arithmetic in which all values are reduced to a specific range by dividing each result by some constant (in this case, the capacity of the array) and taking the remainder. In C++, you can use the % operator to implement modular arithmetic. When you are using the ring-buffer strategy, it is typically necessary to expand the queue when there is still one free element left in the array. If you don’t do so, the simple test for an empty queue—whether head is equal to tail —fails because that would also be true in a completely full queue.When you are using the ring-buffer strategy, it is typically necessary to expand the queue when there is still one free element left in the array. If you don’t do so, the simple test for an empty queue—whether head is equal to tail —fails because that would also be true in a completely full queue.

/* * Implementation notes * * The array-based queue stores the elements in a ring buffer, which * consists of a dynamic index and two indices: head and tail. Each * index wraps to the beginning if necessary. This design requires * that there is always one unused element in the array. If the queue * were allowed to fill completely, the head and tail indices would * have the same value, and the queue will appear empty. */ private: static const int INITIAL_CAPACITY = 10; /* Instance variables */ ValueType *array; /* A dynamic array of the elements */ int capacity; /* The allocated size of the array */ int head; /* The index of the head element */ int tail; /* The index of the tail element */ /* Private method prototypes */ void expandCapacity(); Structure for the Array-Based Queue

/* Implementation section */ /* * Implementation notes: Queue constructor * * The constructor must allocate the array storage for the queue * elements and initialize the fields of the object. */ template Queue ::Queue() { capacity = INITIAL_CAPACITY; array = new ValueType[capacity]; head = 0; tail = 0; } /* * Implementation notes: ~Queue destructor * * The destructor frees any memory that is allocated by the implementation. */ template Queue ::~Queue() { delete[] array; } Code for the Ring-Buffer Queue

/* Implementation section */ /* * Implementation notes: Queue constructor * * The constructor must allocate the array storage for the queue * elements and initialize the fields of the object. */ template Queue ::Queue() { capacity = INITIAL_CAPACITY; array = new ValueType[capacity]; head = 0; tail = 0; } /* * Implementation notes: ~Queue destructor * * The destructor frees any memory that is allocated by the implementation. */ template Queue ::~Queue() { delete[] array; } /* * Implementation notes: size * * The size of the queue can be calculated from the head and tail * indices by using modular arithmetic. */ template int Queue ::size() { return (tail + capacity - head) % capacity; } /* * Implementation notes: isEmpty * * The queue is empty whenever the head and tail indices are * equal. Note that this interpretation means that the queue * cannot be allowed to fill the capacity entirely and must * always leave one unused space. */ template bool Queue ::isEmpty() { return head == tail; } Code for the Ring-Buffer Queue

/* * Implementation notes: size * * The size of the queue can be calculated from the head and tail * indices by using modular arithmetic. */ template int Queue ::size() { return (tail + capacity - head) % capacity; } /* * Implementation notes: isEmpty * * The queue is empty whenever the head and tail indices are * equal. Note that this interpretation means that the queue * cannot be allowed to fill the capacity entirely and must * always leave one unused space. */ template bool Queue ::isEmpty() { return head == tail; } /* * Implementation notes: clear * * The clear method need not take account of where in the * ring buffer any existing data is stored and can simply * set the head and tail index back to the beginning. */ template void Queue ::clear() { head = tail = 0; } /* * Implementation notes: enqueue * * This method must first check to see whether there is * enough room for the element and expand the array storage * if necessary. */ template void Queue ::enqueue(ValueType value) { if (size() == capacity - 1) expandCapacity(); array[tail] = value; tail = (tail + 1) % capacity; } Code for the Ring-Buffer Queue

/* * Implementation notes: clear * * The clear method need not take account of where in the * ring buffer any existing data is stored and can simply * set the head and tail index back to the beginning. */ template void Queue ::clear() { head = tail = 0; } /* * Implementation notes: enqueue * * This method must first check to see whether there is * enough room for the element and expand the array storage * if necessary. */ template void Queue ::enqueue(ValueType value) { if (size() == capacity - 1) expandCapacity(); array[tail] = value; tail = (tail + 1) % capacity; } /* * Implementation notes: dequeue, peek * * These methods must check for an empty queue and report an * error if there is no first element. */ template ValueType Queue ::dequeue() { if (isEmpty()) error("dequeue: Attempting to dequeue an empty queue"); ValueType result = array[head]; head = (head + 1) % capacity; return result; } template ValueType Queue ::peek() { if (isEmpty()) error("peek: Attempting to peek at an empty queue"); return array[head]; } Code for the Ring-Buffer Queue

/* * Implementation notes: dequeue, peek * * These methods must check for an empty queue and report an * error if there is no first element. */ template ValueType Queue ::dequeue() { if (isEmpty()) error("dequeue: Attempting to dequeue an empty queue"); ValueType result = array[head]; head = (head + 1) % capacity; return result; } template ValueType Queue ::peek() { if (isEmpty()) error("peek: Attempting to peek at an empty queue"); return array[head]; } /* * Implementation notes: expandCapacity * * This private method doubles the capacity of the elements array * whenever it runs out of space. To do so, it must allocate a new * array, copy all the elements from the old array to the new one, * and free the old storage. Note that this implementation also * shifts all the elements back to the beginning of the array. */ template void Queue ::expandCapacity() { int count = size(); int oldCapacity = capacity; capacity *= 2; ValueType *oldArray = array; array = new ValueType[capacity]; for (int i = 0; i < count; i++) { array[i] = oldArray[(head + i) % oldCapacity]; } head = 0; tail = count; delete[] oldArray; } #endif Code for the Ring-Buffer Queue

Implementing a Linked-List Queue In some ways, the linked-list implementation of a queue is easier to understand than the ring-buffer model, even though it contains pointers.In some ways, the linked-list implementation of a queue is easier to understand than the ring-buffer model, even though it contains pointers. In the linked-list version, the private data structure for the Queue class requires two pointers to cells: a head pointer that indicates the first cell in the chain, and a tail pointer that indicates the last cell. Because all insertion happens at the tail of the queue, no dummy cell is required.In the linked-list version, the private data structure for the Queue class requires two pointers to cells: a head pointer that indicates the first cell in the chain, and a tail pointer that indicates the last cell. Because all insertion happens at the tail of the queue, no dummy cell is required. The private data structure must also keep track of the number of elements so that the size method can run in O(1) time.The private data structure must also keep track of the number of elements so that the size method can run in O(1) time.

/* * Implementation notes: Queue data structure * * The list-based queue uses a linked list to store the elements * of the queue. To ensure that adding a new element to the tail * of the queue is fast, the data structure maintains a pointer to * the last cell in the queue as well as the first. If the queue is * empty, both the head pointer and the tail pointer are set to NULL. */ private: /* Type for linked list cell */ struct Cell { ValueType data; /* The data value */ Cell *link; /* Link to the next cell */ }; /* Instance variables */ Cell *head; /* Pointer to the cell at the head */ Cell *tail; /* Pointer to the cell at the tail */ int count; /* Number of elements in the queue */ Structure for the List-Based Queue

Tracing the List-Based Queue head Queue queue; count queue.enqueue('A') tail queue.enqueue('B') queue.enqueue('C') queue.dequeue() template Queue ::Queue() { head = tail = NULL; count = 0; } 0  

Tracing the List-Based Queue cp value A head Queue queue; count queue.enqueue('A') tail queue.enqueue('B') queue.enqueue('C') queue.dequeue() queue.dequeue() A template... enqueue(ValueType value) { Cell *cp = new Cell; cp->data = value; cp->link = NULL; if (head == NULL) { head = cp; } else { tail->link = cp; } tail = cp; count++; } 01   1000

cp value B Tracing the List-Based Queue head Queue queue; count queue.enqueue('A') tail queue.enqueue('B') queue.enqueue('C') queue.dequeue() queue.dequeue() A template... enqueue(ValueType value) { Cell *cp = new Cell; cp->data = value; cp->link = NULL; if (head == NULL) { head = cp; } else { tail->link = cp; } tail = cp; count++; } 0 1   1010 B 2

Tracing the List-Based Queue head Queue queue; count queue.enqueue('A') tail queue.enqueue('B') queue.enqueue('C') queue.dequeue() 'A'  queue.dequeue() queue.dequeue() A template ValueType Queue ::dequeue() { if (isEmpty()) error(...); Cell *cp = head; ValueType result = cp->data; head = cp->link; if (head == NULL) tail = NULL; count--; delete cp; return result; } 0 1   cp B 2 result A 1010

cp value C Tracing the List-Based Queue head Queue queue; count queue.enqueue('A') tail queue.enqueue('B') queue.enqueue('C') queue.dequeue() queue.dequeue() C template... enqueue(ValueType value) { Cell *cp = new Cell; cp->data = value; cp->link = NULL; if (head == NULL) { head = cp; } else { tail->link = cp; } tail = cp; count++; } 0 1   'A'  1000 B

Tracing the List-Based Queue head Queue queue; count queue.enqueue('A') tail queue.enqueue('B') queue.enqueue('C') queue.dequeue() queue.dequeue() C 0 1   cp 'A'  1000 B template ValueType Queue ::dequeue() { if (isEmpty()) error(...); Cell *cp = head; ValueType result = cp->data; head = cp->link; if (head == NULL) tail = NULL; count--; delete cp; return result; } 'B'  result B

Tracing the List-Based Queue head Queue queue; count queue.enqueue('A') tail queue.enqueue('B') queue.enqueue('C') queue.dequeue() queue.dequeue() C 01  cp 1000 'A'  template ValueType Queue ::dequeue() { if (isEmpty()) error(...); Cell *cp = head; ValueType result = cp->data; head = cp->link; if (head == NULL) tail = NULL; count--; delete cp; return result; } 'B'  result C 'C' 

/* * Implementation notes: Queue constructor * * The constructor must create an empty linked list and then * initialize the fields of the object. */ template Queue ::Queue() { head = tail = NULL; count = 0; } /* * Implementation notes: ~Queue destructor * * The destructor frees any memory that is allocated by the implementation. * Freeing this memory guarantees the client that the queue abstraction * will not "leak memory" in the process of running an application. * Because clear frees each element it processes, this implementation * of the destructor simply calls that method. */ template Queue ::~Queue() { clear(); } Code for the Linked-List Queue

/* * Implementation notes: Queue constructor * * The constructor must create an empty linked list and then * initialize the fields of the object. */ template Queue ::Queue() { head = tail = NULL; count = 0; } /* * Implementation notes: ~Queue destructor * * The destructor frees any memory that is allocated by the implementation. * Freeing this memory guarantees the client that the queue abstraction * will not "leak memory" in the process of running an application. * Because clear frees each element it processes, this implementation * of the destructor simply calls that method. */ template Queue ::~Queue() { clear(); } /* * Implementation notes: size, isEmpty, clear * * These implementations should be self-explanatory. */ template int Queue ::size() { return count; } template bool Queue ::isEmpty() { return count == 0; } template void Queue ::clear() { while (count > 0) { dequeue(); } Code for the Linked-List Queue

/* * Implementation notes: size, isEmpty, clear * * These implementations should be self-explanatory. */ template int Queue ::size() { return count; } template bool Queue ::isEmpty() { return count == 0; } template void Queue ::clear() { while (count > 0) { dequeue(); } /* * Implementation notes: enqueue * * This method allocates a new list cell and chains it in * at the tail of the queue. If the queue is currently empty, * the new cell must also become the head pointer in the queue. */ template void Queue ::enqueue(ValueType value) { Cell *cp = new Cell; cp->data = value; cp->link = NULL; if (head == NULL) { head = cell; } else { tail->link = cell; } tail = cell; count++; } Code for the Linked-List Queue

/* * Implementation notes: enqueue * * This method allocates a new list cell and chains it in * at the tail of the queue. If the queue is currently empty, * the new cell must also become the head pointer in the queue. */ template void Queue ::enqueue(ValueType value) { Cell *cp = new Cell; cp->data = value; cp->link = NULL; if (head == NULL) { head = cell; } else { tail->link = cell; } tail = cell; count++; } /* * Implementation notes: dequeue, peek * * These methods must check for an empty queue and report an * error if there is no first element. The dequeue method * must also check for the case in which the queue becomes * empty and set both the head and tail pointers to NULL. */ template ValueType Queue ::dequeue() { if (isEmpty()) error("dequeue: Attempting to dequeue an empty queue"); Cell *cp = head; ValueType result = cp->data; head = cp->link; if (head == NULL) tail = NULL; count--; delete cell; return result; } template ValueType Queue ::peek() { if (isEmpty()) error("peek: Attempting to peek at an empty queue"); return head->data; } Code for the Linked-List Queue

The End