1 c++ classes and data structures jeffrey s. childs chapter 8 stacks and queues jeffrey s. childs...
TRANSCRIPT
1
C++ Classes and Data StructuresJeffrey S. Childs
Chapter 8
Stacks and Queues
Jeffrey S. Childs
Clarion University of PA
© 2008, Prentice Hall
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, the set of data is the stack of elements
3
Stack ADT Operations
• push: places an element onto the top of a stack• pop: removes an element from the top of the
stack• peek: which retrieves (copies) a value from the
top of the stack without removing it• an operation to determine whether or not the
stack is empty• an operation to empty out a stack
4
Push
17
5
11
3
• Push means place a new data element at the top of the stack
5
Push (cont.)
17
5
11
3
• Push means place a new data element at the top of the stack
6
Push (cont.)
17
5
11
3
• Push means place a new data element at the top of the stack
7
Push (cont.)
17
5
11
3
• Push means place a new data element at the top of the stack
8
Pop
17
5
11
3
• Pop means take a data element off the top of the stack
9
Pop (cont.)
17
5
11
3
• Pop means take a data element off the top of the stack
10
Pop (cont.)
17
5
11
3
• Pop means take a data element off the top of the stack
11
Pop (cont.)
17
5
11
3
• Pop means take a data element off the top of the stack
12
Peek
17
5
11
3
• Peek means retrieve the top of the stack without removing it
13
Peek (cont.)
17
5
11
3
3
• Peek means retrieve the top of the stack without removing it
14
Peek (cont.)
17
5
11
3
3
• Peek means retrieve the top of the stack without removing it
15
1 #include “Array.h”2
3 template <class DataType>4 class Stack5 {6 public:7 Stack( );8 void push( DataType elementToPush ); 9 bool pop( DataType & poppedElement );10 bool peek( DataType & topElement ); 11 bool isEmpty( ) const; 12 void makeEmpty( );13 private:14 Array<DataType> elements;15 int top;16 };1718 #include “Stack.cpp”
Stack Class Template
16
1 #include “Array.h”2
3 template <class DataType>4 class Stack5 {6 public:7 Stack( );8 void push( DataType elementToPush ); 9 bool pop( DataType & poppedElement );10 bool peek( DataType & topElement ); 11 bool isEmpty( ) const; 12 void makeEmpty( );
13 private:14 Array<DataType> elements;15 int top;16 };17
18 #include “Stack.cpp”
Stack Class Template (cont.)
17
1 #include “Array.h”2
3 template <class DataType>4 class Stack5 {6 public:7 Stack( );8 void push( DataType elementToPush ); 9 bool pop( DataType & poppedElement );10 bool peek( DataType & topElement ); 11 bool isEmpty( ) const; 12 void makeEmpty( );
13 private:14 Array<DataType> elements;15 int top;16 };17
18 #include “Stack.cpp”
Stack Class Template (cont.)
used as an index to the top of the stack
18
The Actual Pop
125 25 200 70
elements
0 1 2 3 top
An element can’t really be removed from an array, as one would think pop would achieve.
19
The Actual Pop(cont.)
125 25 200 70
elements
0 1 2 3 top
The element 70 is at the top of the stack, and what really happens during a pop, is that 70 is returned to the client…
20
The Actual Pop(cont.)
125 25 200 70
elements
0 1 2 3 top
The element 70 is at the top of the stack, and what really happens during a pop, is that 70 is returned to the client…
client
21
The Actual Pop(cont.)
125 25 200 70
elements
0 1 2 3 top
and top is decremented…
client
22
The Actual Pop(cont.)
125 25 200 70
elements
0 1 2 3 top
and top is decremented…
client
23
The Actual Pop(cont.)
125 25 200 70
elements
0 1 2 3 top
The element 70 is still in the array, but it is no longer accessible. The next push will overwrite it. Say, we would like to push 63…
client
24
The Actual Push(cont.)
125 25 200 70
elements
0 1 2 3 top
First, top is incremented…
25
The Actual Push(cont.)
125 25 200 70
elements
0 1 2 3 top
First, top is incremented…
26
The Actual Push(cont.)
125 25 200 70
elements
0 1 2 3 top
Then, 63 is pushed into that position…
27
The Actual Push(cont.)
125 25 200 63
elements
0 1 2 3 top
Then, 63 is pushed into that position…
28
1 template <class DataType>2 Stack<DataType>::Stack( )3 : elements( 2 ), top( -1 )4 {5 }
Stack Constructor
29
Shift Operators
• Shift operators are used in the array implementations of data structures
• They are appropriate when multiplying or dividing by powers of two
• They are faster than multiplication and division• Assume num is a positive integer.• num << n is the same as num * 2n
• num >> n is the same as num / 2n (using integer division)
30
Push Code
6 template <class DataType>7 void Stack<DataType>::push( 8 DataType elementToPush )9 {10 if ( ++top == elements.length( ) )11 elements.changeSize( elements.length( ) << 1 ); 12 elements[ top ] = elementToPush;13 }
31
Pop
• Recall…to conserve memory, if the number of used elements of an array drops to 25% of the capacity, we want to cut the capacity of the array in half
• On each pop, it is possible that we may want to reduce the size of the array
32
Reducing Array Size
• When we call the changeSize function for the Array object, it is possible that there is not enough heap memory to reduce the array size
• A new, smaller dynamic array needs to be created to copy the elements of the old, larger dynamic array to it
• If the smaller array cannot be created the pop function should still succeed (stack is still completely functional)
33
Reducing Array Size (cont.)
• If array size reduction does not succeed, it might succeed later on– Other dynamic memory may be freed– The number of used elements in the stack may drop
so low that a small dynamic array can be made
• Therefore, in the pop function, we should try to reduce the size to the smallest power of 2, which is:– At least twice the number of elements being used– At least 2
34
Example
• Suppose there are 3 elements being used in a stack.
• top would be 2, so top + 1 gives the number of elements
• Suppose also that the capacity of the array is 32.
• The array’s capacity should be reduced to 8 (one quarter of the capacity instead of one half)
35
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize:
36
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize:
37
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 32
38
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 32
39
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 32Number of elements: 3
40
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 32Number of elements: 3
41
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 32Number of elements: 3
trysize / 4 : 8
42
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 32Number of elements: 3
trysize / 4 : 8
TRUE
43
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 32Number of elements: 3
trysize / 4 : 8
TRUE
44
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 32Number of elements: 3
trysize / 4 : 8
TRUE
TRUE
45
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 32
46
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 16
47
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 16
48
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 16
3 <= 4 : TRUE
49
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 16
3 <= 4 : TRUE
50
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 16
3 <= 4 : TRUETRUE
51
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 16
52
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 8
53
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 8
54
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 8
3 <= 2 : FALSE
55
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 8
56
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 8
trysize will be the new capacity that we attempt to use (might be out of heap memory)
57
Example (cont.)
int trysize = elements.length( );while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )
trysize >>= 1;
top: 2
capacity: 32
trysize: 8
If trysize would become 2, this part would be false, causing 2 to be the smallest possible capacity
58
14 template <class DataType>15 bool Stack<DataType>::pop( 16 DataType & poppedElement )17 {18 if ( top == -1 ) 19 return false;20 poppedElement = elements[ top ];21 top--;22 int trysize = elements.length( );23 while ( ( top + 1 <= trysize >> 2 ) && trysize > 2 )24 trysize >>= 1;
Pop Code
Pop code continued…
59
Pop Code (cont.)
25 if ( trysize < elements.length( ) ) {26 try {27 elements.changeSize( trysize );28 }29 catch( … ) { }30 }3132 return true;33 }
60
Peek
34 // returns the element at the top of the stack in 35 // topElement without removing it. Returns false if 36 // called on an empty stack; otherwise, returns true37 template <class DataType>38 bool Stack<DataType>::peek( 39 DataType & topElement )40 {41 if ( top == -1 ) 42 return false;43 topElement = elements[ top ];44 return true;45 }
61
46 template <class DataType>47 bool Stack<DataType>::isEmpty( ) const48 {49 return top == -1;50 }
isEmpty
62
makeEmpty
51 template <class DataType>52 void Stack<DataType>::makeEmpty( )53 {54 top = -1;55 try {56 elements.changeSize( 2 );57 }58 catch( … ) { }59 }
63
Linked-List Stack
• Stacks can also be implemented with a linked list
• The front node is the top of the stack
64
Linked-List Stack(cont.)
top
To pop, we remove the node at the front of the linked list, and return the element to the client…
65
Linked-List Stack(cont.)
top
To pop, we remove the node at the front of the linked list, and return the element to the client…
66
Linked-List Stack(cont.)
top
To push, we place the new element in a node and insert it at the front of the linked list…
67
Linked-List Stack(cont.)
To push, we place a new element in a node and insert it at the front of the linked list…
top
68
The Queue ADT
• The queue is a data structure that is like a line of people, except that it is a line of elements
• The line of elements is the data upon which operations are performed
69
Queue ADT Operations
• enqueue: add an element to the end of the line
• dequeue: take an element from the front of the line
• peek: retrieve (copy) the element at the front of the line without removing it
• an operation to determine whether or not the queue is empty
• an operation that will empty out the queue
70
Queue
• A queue is like a line of people• When people join the line, they go at the
end• When people are served, they come off
the front of the line• A queue is a FIFO (first-in, first-out) data
structure• It is used in situations where a fair first-
come, first-serve basis is called for, like a print queue
71
Queue (cont.)
• In addition to a pointer at the beginning of the linked list (called front), a pointer to the end of the linked list (called back) is also maintained in the private section
• The back pointer makes it fast to add new elements to the end of the queue – you don’t have to use a loop to go all the way through the queue to find the last node
72
Header Node
• A header node can simplify the code for a linked-list queue
• We make use of a header node in the queue implementation
73
Dequeue Operation
front back
header
74
Dequeue Operation(cont.)
front back
header
75
Enqueue Operation
front back
header
76
Enqueue Operation(cont.)
front back
header
77
1 // queue.h -- class template for the linked list 2 // implementation of a queue3 // note: use of the copy constructor, overloaded 4 // assignment operator, or enqueue function can cause an 5 // exception to be thrown when heap memory is exhausted67 template <class DataType>8 struct Node {9 DataType info;10 Node<DataType> *next;11 };
Queue Specification File
Specification File continued…
78
Queue Specification File (cont.)
12 template <class DataType>13 class Queue14 {15 public:16 Queue( );17 Queue( const Queue<DataType> & apqueue ); 18 ~Queue( );19 Queue<DataType> & operator =( 20 const Queue<DataType> & rqueue );
public section of Queue continued…
79
Queue Specification File (cont.)
21 void enqueue( const DataType & element );22 bool dequeue( DataType & deqElement );23 bool peek( DataType & frontElement ); 24 bool isEmpty( ) const;25 void makeEmpty( );
private section of Queue is next…
80
Queue Specification File (cont.)
26 private:27 Node<DataType> *front;28 Node<DataType> *back;29 Node<DataType> header;30 inline void deepCopy( 31 const Queue<DataType> & original );32 };3334 #include "queue.cpp"
81
1 // queue.cpp 23 template <class DataType>4 Queue<DataType>::Queue( )5 {6 front = back = &header;7 }
Queue Constructor
82
Queue Copy Constructor and Destructor
8 template <class DataType>9 Queue<DataType>::Queue( 10 const Queue<DataType> & apqueue )11 {12 deepCopy( apqueue );13 }1415 template <class DataType>16 Queue<DataType>::~Queue( )17 {18 makeEmpty( );19 }
83
Queue OverloadedAssignment Operator
20 template <class DataType>21 Queue<DataType> & Queue<DataType>::22 operator =( const Queue<DataType> & rqueue )23 {24 if ( this == &rqueue )25 return *this;26 makeEmpty( );27 deepCopy( rqueue );28 return *this;29 }
84
Enqueue
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
This section creates the new node to enqueue and places element within in it…
85
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
This section creates the new node to enqueue and places element within in it…
ptr
86
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
Let’s consider a couple of cases with these next two lines.
ptr
87
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
Let’s consider a couple of cases with these next two lines.
ptr
88
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
Case 1: The queue is initially empty.
ptr
89
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
Case 1: The queue is initially empty.
front
ptr
header
back
90
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
Case 1: The queue is initially empty.
front
ptr
header
back
91
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
Case 1: The queue is initially empty.
front
ptr
header
back
92
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
Case 1: The queue is initially empty.
front
ptr
header
back
93
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
Case 1: The queue is initially empty.
front
ptr
headerback
94
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
Case 2: The queue has nodes.
ptr
95
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
Case 2: The queue has nodes.
ptr
front
header
back
96
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
Case 2: The queue has nodes.
ptr
front
header
back
97
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
Case 2: The queue has nodes.
ptr
front
header
back
98
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
Case 2: The queue has nodes.
ptr
front
header
back
99
Enqueue (cont.)
30 template <class DataType>31 void Queue<DataType>::enqueue( 32 const DataType & element )33 {34 Node<DataType> *ptr = new Node<DataType>;35 ptr->info = element;36 back->next = ptr;37 back = ptr;38 }
Case 2: The queue has nodes.
ptr
front
headerback
100
Dequeue
39 template <class DataType>40 bool Queue<DataType>::dequeue( 41 DataType & deqElement )42 {43 if ( front == back ) 44 return false;
Dequeue continued…
Returns false if client tries to dequeue an empty queue.
101
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
102
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
103
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
104
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
105
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
deqElement:
passed in by reference
106
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
deqElement:
107
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
deqElement:
108
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
deqElement:
109
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
deqElement:
110
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
deqElement:
111
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
Let’s consider what happens if only one node is left to dequeue.
112
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
Let’s consider what happens if only one node is left to dequeue.
113
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
114
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
115
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
116
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
deqElement:
117
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
deqElement:
118
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
deqElement:
119
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
deqElement:
120
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
backheader
ptr
deqElement:
121
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
headerptr
deqElement:
back
122
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
headerptr
deqElement:
back
123
Dequeue (cont.)
45 Node<DataType> *ptr = front->next;46 deqElement = ptr->info;47 front->next = ptr->next;48 if ( back == ptr )49 back = front;50 delete ptr;5152 return true;53 }
front
headerptr
deqElement:
back
124
Peek
54 template <class DataType>55 bool Queue<DataType>::peek( 56 DataType & frontElement )57 {58 if ( front == back )59 return false;60 frontElement = front->next->info;61 return true;62 }
125
isEmpty and makeEmpty
63 template <class DataType>64 bool Queue<DataType>::isEmpty( ) const65 {66 return front == back;67 }6869 template <class DataType>70 void Queue<DataType>::makeEmpty( )71 {72 DataType temp;73 while ( dequeue( temp ) );74 }
126
deepCopy75 template <class DataType>76 inline void Queue<DataType>::deepCopy( 77 const Queue<DataType> & original )78 {79 Node<DataType> *copyptr = front = &header; 80 Node<DataType> *originalptr = original.front;
front back
Original Copy
header header
127
deepCopy75 template <class DataType>76 inline void Queue<DataType>::deepCopy( 77 const Queue<DataType> & original )78 {79 Node<DataType> *copyptr = front = &header; 80 Node<DataType> *originalptr = original.front;
front back
Original Copy
header header
128
deepCopy75 template <class DataType>76 inline void Queue<DataType>::deepCopy( 77 const Queue<DataType> & original )78 {79 Node<DataType> *copyptr = front = &header; 80 Node<DataType> *originalptr = original.front;
front back
Original Copy
header header
frontcopyptr
129
deepCopy75 template <class DataType>76 inline void Queue<DataType>::deepCopy( 77 const Queue<DataType> & original )78 {79 Node<DataType> *copyptr = front = &header; 80 Node<DataType> *originalptr = original.front;
front back
Original Copy
header header
frontcopyptr
130
deepCopy75 template <class DataType>76 inline void Queue<DataType>::deepCopy( 77 const Queue<DataType> & original )78 {79 Node<DataType> *copyptr = front = &header; 80 Node<DataType> *originalptr = original.front;
front back
Original Copy
header header
frontoriginalptr copyptr
131
deepCopy75 template <class DataType>76 inline void Queue<DataType>::deepCopy( 77 const Queue<DataType> & original )78 {79 Node<DataType> *copyptr = front = &header; 80 Node<DataType> *originalptr = original.front;
front back
Original Copy
header header
frontoriginalptr copyptr
deepCopy function continued…
132
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
133
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
134
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
135
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
136
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
137
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
138
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
139
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
140
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
141
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
142
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
143
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
144
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
145
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
146
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
147
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
148
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
149
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
150
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
151
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
152
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
153
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
154
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
155
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
156
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
157
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
158
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
159
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
160
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
161
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
back
162
deepCopy (cont.)81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
front back
Original Copy
header header
frontoriginalptr copyptr
back
Let’s consider the empty case…
163
deepCopy (cont.)75 template <class DataType>76 inline void Queue<DataType>::deepCopy( 77 const Queue<DataType> & original )78 {79 Node<DataType> *copyptr = front = &header; 80 Node<DataType> *originalptr = original.front;
front back
Original Copy
header header
164
deepCopy (cont.)75 template <class DataType>76 inline void Queue<DataType>::deepCopy( 77 const Queue<DataType> & original )78 {79 Node<DataType> *copyptr = front = &header; 80 Node<DataType> *originalptr = original.front;
front back
Original
header
Copy
header
frontcopyptr
165
deepCopy (cont.)75 template <class DataType>76 inline void Queue<DataType>::deepCopy( 77 const Queue<DataType> & original )78 {79 Node<DataType> *copyptr = front = &header; 80 Node<DataType> *originalptr = original.front;
front back
Original
header
Copy
header
frontcopyptr
166
deepCopy (cont.)75 template <class DataType>76 inline void Queue<DataType>::deepCopy( 77 const Queue<DataType> & original )78 {79 Node<DataType> *copyptr = front = &header; 80 Node<DataType> *originalptr = original.front;
front back
Original
header
Copy
header
frontcopyptr
originalptr
167
deepCopy (cont.)75 template <class DataType>76 inline void Queue<DataType>::deepCopy( 77 const Queue<DataType> & original )78 {79 Node<DataType> *copyptr = front = &header; 80 Node<DataType> *originalptr = original.front;
front back
Original
header
Copy
header
frontcopyptr
originalptr
168
deepCopy (cont.)
front back
Original
header
Copy
header
frontcopyptr
originalptr
81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
169
deepCopy (cont.)
front back
Original
header
Copy
header
frontcopyptr
originalptr
81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
170
deepCopy (cont.)
front back
Original
header
Copy
header
frontcopyptr
originalptr
81 while ( originalptr != original.back ) {82 originalptr = originalptr->next;83 copyptr->next = new Node<DataType>;84 copyptr = copyptr->next;85 copyptr->info = originalptr->info;86 }87 back = copyptr;88 }
back
171
Array Implementation of a Queue
• Similar to the linked-list queue, there are two data members called front and back, but they are indexes into an Array instead of pointers
• When enqueuing, the back index is incremented, and when dequeuing, the front index is incremented
172
Enqueue / Dequeue
0 1 2 3 4 5 6 7
front back
173
0 1 2 3 4 5 6 7
front back
DEQUEUE
Enqueue / Dequeue(cont.)
174
0 1 2 3 4 5 6 7
front back
DEQUEUE
Enqueue / Dequeue(cont.)
175
0 1 2 3 4 5 6 7
front back
DEQUEUE
Enqueue / Dequeue(cont.)
176
0 1 2 3 4 5 6 7
front back
DEQUEUE
Enqueue / Dequeue(cont.)
177
0 1 2 3 4 5 6 7
front back
ENQUEUE
Enqueue / Dequeue(cont.)
178
0 1 2 3 4 5 6 7
front back
ENQUEUE
Enqueue / Dequeue(cont.)
179
0 1 2 3 4 5 6 7
front back
ENQUEUE
Enqueue / Dequeue(cont.)
180
0 1 2 3 4 5 6 7
front back
ENQUEUE
Enqueue / Dequeue(cont.)
181
0 1 2 3 4 5 6 7
front back
DEQUEUE
Enqueue / Dequeue(cont.)
182
0 1 2 3 4 5 6 7
front back
DEQUEUE
Enqueue / Dequeue(cont.)
183
0 1 2 3 4 5 6 7
front back
DEQUEUE
Enqueue / Dequeue(cont.)
184
0 1 2 3 4 5 6 7
front back
DEQUEUE
Enqueue / Dequeue(cont.)
185
0 1 2 3 4 5 6 7
front back
ENQUEUE
Enqueue / Dequeue(cont.)
186
0 1 2 3 4 5 6 7
front back
ENQUEUE
Enqueue / Dequeue(cont.)
187
0 1 2 3 4 5 6 7
front back
DEQUEUE
Enqueue / Dequeue(cont.)
188
0 1 2 3 4 5 6 7
front back
DEQUEUE
Enqueue / Dequeue(cont.)
189
0 1 2 3 4 5 6 7
front back
DEQUEUE
Enqueue / Dequeue(cont.)
190
0 1 2 3 4 5 6 7
front back
ENQUEUE
Enqueue / Dequeue(cont.)
191
0 1 2 3 4 5 6 7
front back
ENQUEUE
?
Enqueue / Dequeue(cont.)
192
0 1 2 3 4 5 6 7
front back
ENQUEUE
Enqueue / Dequeue(cont.)
We could double the size of the array here.
193
0 1 2 3 4 5 6 7
front back
ENQUEUE
Enqueue / Dequeue(cont.)
But if we keep doing this, we may have a million elements in the Array, but only a few at the end are used!
194
0 1 2 3 4 5 6 7
front back
ENQUEUE
Enqueue / Dequeue(cont.)
We handle this problem by having the back wrap around to the beginning of the array.
195
0 1 2 3 4 5 6 7
frontback
ENQUEUE
Enqueue / Dequeue(cont.)
196
0 1 2 3 4 5 6 7
frontback
The front also wraps to the beginning when it reaches the end of the array
Enqueue / Dequeue(cont.)
197
How Do We Know When the Array is Full?
• We may still need to double the capacity of the array if it gets filled
• An array will be full when– back + 1 == front– OR– back + 1 == capacity AND front == 0
198
A Full Array
0 1 2 3 4 5 6 7
frontback
199
A Full Array
0 1 2 3 4 5 6 7
frontback
If the next operation is ENQUEUE, the array capacity will need to be doubled
200
The Queue ClassTemplate
1 #include "Array.h"23 template <class DataType>4 class Queue5 {6 public:7 Queue( );8 void enqueue( DataType element );9 bool dequeue( DataType & deqElement ); 10 bool peek( DataType & frontElement );11 bool isEmpty( ) const;12 void makeEmpty( );
201
The Queue ClassTemplate (cont.)
13 private:14 Array<DataType> elements;15 int front;16 int back;17 };1819 #include "queue.cpp"
202
Queue Constructor
1 // queue.cpp 2 template <class DataType>3 Queue<DataType>::Queue( )4 : elements( 2 ), front( -1 ), back( -1 )5 {6 }
203
Enqueue7 template <class DataType>8 void Queue<DataType>::enqueue( DataType element )9 {10 if ( back + 1 == front || 11 ( back == elements.length( ) - 1 && !front ) ) {12 elements.changeSize( elements.length( ) << 1 );13 // if front end was last part of array, readjust14 if ( back < front ) {15 int i = elements.length( ) - 1;16 for ( int j = ((i + 1) >> 1) - 1; j >= front; i--, j-- )17 elements[ i ] = elements[ j ];18 front = i + 1;19 }20 }
Enqueue continued…
204
Enqueue (cont.)
21 if ( back == -1 ) // queue is empty22 front = 0;23 back = (back == elements.length( ) - 1)? 24 0 : back + 1;25 elements[ back ] = element;26 }
205
Dequeue
27 template <class DataType>28 bool Queue<DataType>::dequeue( 29 DataType & deqElement )30 {31 if (front == -1 )32 return false;
Dequeue continued…
206
Dequeue (cont.)
33 deqElement = elements[ front ];34 if ( front == back ) // only one element was in queue35 front = back = -1;36 else37 front = (front == elements.length( ) - 1)? 38 0 : front + 1;
Dequeue continued…
207
Dequeue (cont.)
39 // try to reduce the size of the array40 int trysize = elements.length( );41 int numElements = (front <= back)? 42 back - front + 1 : back + trysize - front + 1;43 while ( ( numElements <= trysize >> 2 ) && trysize > 2 ) 44 trysize >>= 1;
Dequeue continued…
208
Dequeue (cont.)
45 if ( trysize < elements.length( ) ) {46 // readjust so we won't lose elements when 47 // shrinking the array size48 int i, j;49 if ( front > back ) {
If true, we can try to change the size of the array…
The code for the “front > back” case is shown next…
209
Dequeue (cont.)
50 for ( i = trysize - 1, j = elements.length( ) - 1; j >= front; i--, j-- )51 elements[ i ] = elements[ j ];52 front = i + 1;53 try {54 elements.changeSize( trysize );55 }56 catch( … ) {57 for ( i = elements.length( ) - 1, j = trysize - 1; j >= front; i--, j-- )58 elements[ i ] = elements[ j ];59 front = i + 1;60 }
If we can’t change the size, we’ll have to undo the realignment on lines 50-52.
210
Dequeue (cont.)
61 return true;62 }63 else if ( front <= back && back >= trysize ) {64 for ( i = 0, j = front; j <= back; i++, j++ )65 elements[ i ] = elements[ j ];66 front = 0;67 back = i - 1;68 }
We need to return for the “front > back” case
We won’t need to undo this realignment if we can’t change the size.
We’re ready for the changeSize attempt…
211
Dequeue (cont.)
69 try {70 elements.changeSize( trysize );71 }72 catch( … ) { }73 }7475 return true;76 }
This changeSize attempt handles the “front <= back && back >= trysize” case AND the case where no realignment is necessary:
“front <= back && back < trysize”
212
Peek
77 template <class DataType>78 bool Queue<DataType>::peek( 79 DataType & frontElement )80 {81 if (front == -1 )82 return false;83 frontElement = elements[ front ];84 return true;85 }
213
isEmpty
86 template <class DataType>87 bool Queue<DataType>::isEmpty( ) const88 {89 return front == -1;90 }
214
makeEmpty
91 template <class DataType>92 void Queue<DataType>::makeEmpty( )93 {94 front = back = -1;95 try {96 elements.changeSize( 2 );97 }98 catch( … ) { }99 }