1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 8 Stacks and Queues Jeffrey S. Childs...

Post on 28-Dec-2015

222 views 0 download

Tags:

Transcript of 1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 8 Stacks and Queues Jeffrey S. Childs...

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 }