Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 8 Stacks and Queues Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall.

Similar presentations


Presentation on theme: "1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 8 Stacks and Queues Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall."— Presentation transcript:

1 1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 8 Stacks and Queues Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall

2 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 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 4 Push 17 5 11 3 Push means place a new data element at the top of the stack

5 5 Push (cont.) 17 5 11 3 Push means place a new data element at the top of the stack

6 6 Push (cont.) 17 5 11 3 Push means place a new data element at the top of the stack

7 7 Push (cont.) 17 5 11 3 Push means place a new data element at the top of the stack

8 8 Pop 17 5 11 3 Pop means take a data element off the top of the stack

9 9 Pop (cont.) 17 5 11 3 Pop means take a data element off the top of the stack

10 10 Pop (cont.) 17 5 11 3 Pop means take a data element off the top of the stack

11 11 Pop (cont.) 17 5 11 3 Pop means take a data element off the top of the stack

12 12 Peek 17 5 11 3 Peek means retrieve the top of the stack without removing it

13 13 Peek (cont.) 17 5 11 3 3 Peek means retrieve the top of the stack without removing it

14 14 Peek (cont.) 17 5 11 3 3 Peek means retrieve the top of the stack without removing it

15 15 1 #include “Array.h” 2 3 template 4 class Stack 5 { 6 public: 7Stack( ); 8void push( DataType elementToPush ); 9bool pop( DataType & poppedElement ); 10bool peek( DataType & topElement ); 11bool isEmpty( ) const; 12void makeEmpty( ); 13 private: 14Array elements; 15int top; 16 }; 17 18 #include “Stack.cpp” Stack Class Template

16 16 1 #include “Array.h” 2 3 template 4 class Stack 5 { 6 public: 7Stack( ); 8void push( DataType elementToPush ); 9bool pop( DataType & poppedElement ); 10bool peek( DataType & topElement ); 11bool isEmpty( ) const; 12void makeEmpty( ); 13 private: 14Array elements; 15int top; 16 }; 17 18 #include “Stack.cpp” Stack Class Template (cont.)

17 17 1 #include “Array.h” 2 3 template 4 class Stack 5 { 6 public: 7Stack( ); 8void push( DataType elementToPush ); 9bool pop( DataType & poppedElement ); 10bool peek( DataType & topElement ); 11bool isEmpty( ) const; 12void makeEmpty( ); 13 private: 14Array elements; 15int top; 16 }; 17 18 #include “Stack.cpp” Stack Class Template (cont.) used as an index to the top of the stack

18 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 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 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 21 The Actual Pop (cont.) 125 25 200 70 elements 0 1 2 3 top and top is decremented… client

22 22 The Actual Pop (cont.) 125 25 200 70 elements 0 1 2 3 top and top is decremented… client

23 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 24 The Actual Push (cont.) 125 25 200 70 elements 0 1 2 3 top First, top is incremented…

25 25 The Actual Push (cont.) 125 25 200 70 elements 0 1 2 3 top First, top is incremented…

26 26 The Actual Push (cont.) 125 25 200 70 elements 0 1 2 3 top Then, 63 is pushed into that position…

27 27 The Actual Push (cont.) 125 25 200 63 elements 0 1 2 3 top Then, 63 is pushed into that position…

28 28 1 template 2 Stack ::Stack( ) 3: elements( 2 ), top( -1 ) 4 { 5 } Stack Constructor

29 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 * 2 n num >> n is the same as num / 2 n (using integer division)

30 30 Push Code 6 template 7 void Stack ::push( 8DataType elementToPush ) 9 { 10if ( ++top == elements.length( ) ) 11 elements.changeSize( elements.length( ) << 1 ); 12elements[ top ] = elementToPush; 13 }

31 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 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 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 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 35 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:

36 36 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:

37 37 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:32

38 38 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:32

39 39 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:32 Number of elements: 3

40 40 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:32 Number of elements: 3

41 41 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:32 Number of elements: 3 trysize / 4 : 8

42 42 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:32 Number of elements: 3 trysize / 4 : 8 TRUE

43 43 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:32 Number of elements: 3 trysize / 4 : 8 TRUE

44 44 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:32 Number of elements: 3 trysize / 4 : 8 TRUE

45 45 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:32

46 46 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:16

47 47 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:16

48 48 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:16 3 <= 4 : TRUE

49 49 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:16 3 <= 4 : TRUE

50 50 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:16 3 <= 4 : TRUE TRUE

51 51 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:16

52 52 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:8

53 53 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:8

54 54 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:8 3 <= 2 : FALSE

55 55 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 2 ) && trysize > 2 ) trysize >>= 1; top:2 capacity:32 trysize:8

56 56 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 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 57 Example (cont.) int trysize = elements.length( ); while ( ( top + 1 > 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 58 14 template 15 bool Stack ::pop( 16DataType & poppedElement ) 17 { 18if ( top == -1 ) 19return false; 20poppedElement = elements[ top ]; 21top--; 22int trysize = elements.length( ); 23while ( ( top + 1 > 2 ) && trysize > 2 ) 24trysize >>= 1; Pop Code Pop code continued…

59 59 Pop Code (cont.) 25if ( trysize < elements.length( ) ) { 26try { 27elements.changeSize( trysize ); 28} 29catch( … ) { } 30} 31 32return true; 33 }

60 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 true 37 template 38 bool Stack ::peek( 39 DataType & topElement ) 40 { 41if ( top == -1 ) 42return false; 43topElement = elements[ top ]; 44return true; 45 }

61 61 46 template 47 bool Stack ::isEmpty( ) const 48 { 49return top == -1; 50 } isEmpty

62 62 makeEmpty 51 template 52 void Stack ::makeEmpty( ) 53 { 54top = -1; 55try { 56elements.changeSize( 2 ); 57} 58catch( … ) { } 59 }

63 63 Linked-List Stack Stacks can also be implemented with a linked list The front node is the top of the stack

64 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 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 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 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 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 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 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 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 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 73 Dequeue Operation front back header

74 74 Dequeue Operation (cont.) front back header

75 75 Enqueue Operation front back header

76 76 Enqueue Operation (cont.) front back header

77 77 1 // queue.h -- class template for the linked list 2 // implementation of a queue 3 // 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 exhausted 6 7 template 8 struct Node { 9DataType info; 10Node *next; 11 }; Queue Specification File Specification File continued…

78 78 Queue Specification File (cont.) 12 template 13 class Queue 14 { 15 public: 16Queue( ); 17Queue( const Queue & apqueue ); 18~Queue( ); 19Queue & operator =( 20 const Queue & rqueue ); public section of Queue continued…

79 79 Queue Specification File (cont.) 21void enqueue( const DataType & element ); 22bool dequeue( DataType & deqElement ); 23bool peek( DataType & frontElement ); 24bool isEmpty( ) const; 25void makeEmpty( ); private section of Queue is next…

80 80 Queue Specification File (cont.) 26 private: 27Node *front; 28Node *back; 29Node header; 30inline void deepCopy( 31const Queue & original ); 32 }; 33 34 #include "queue.cpp"

81 81 1 // queue.cpp 2 3 template 4 Queue ::Queue( ) 5 { 6front = back = &header; 7 } Queue Constructor

82 82 Queue Copy Constructor and Destructor 8 template 9 Queue ::Queue( 10const Queue & apqueue ) 11 { 12deepCopy( apqueue ); 13 } 14 15 template 16 Queue ::~Queue( ) 17 { 18makeEmpty( ); 19 }

83 83 Queue Overloaded Assignment Operator 20 template 21 Queue & Queue :: 22 operator =( const Queue & rqueue ) 23 { 24if ( this == &rqueue ) 25return *this; 26makeEmpty( ); 27deepCopy( rqueue ); 28return *this; 29 }

84 84 Enqueue 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } This section creates the new node to enqueue and places element within in it…

85 85 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } This section creates the new node to enqueue and places element within in it… ptr

86 86 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } Let’s consider a couple of cases with these next two lines. ptr

87 87 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } Let’s consider a couple of cases with these next two lines. ptr

88 88 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } Case 1: The queue is initially empty. ptr

89 89 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } Case 1: The queue is initially empty. front ptr header back

90 90 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } Case 1: The queue is initially empty. front ptr header back

91 91 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } Case 1: The queue is initially empty. front ptr header back

92 92 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } Case 1: The queue is initially empty. front ptr header back

93 93 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } Case 1: The queue is initially empty. front ptr header back

94 94 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } Case 2: The queue has nodes. ptr

95 95 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } Case 2: The queue has nodes. ptr front header back

96 96 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } Case 2: The queue has nodes. ptr front header back

97 97 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } Case 2: The queue has nodes. ptr front header back

98 98 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } Case 2: The queue has nodes. ptr front header back

99 99 Enqueue (cont.) 30 template 31 void Queue ::enqueue( 32const DataType & element ) 33 { 34Node *ptr = new Node ; 35ptr->info = element; 36back->next = ptr; 37back = ptr; 38 } Case 2: The queue has nodes. ptr front header back

100 100 Dequeue 39 template 40 bool Queue ::dequeue( 41DataType & deqElement ) 42 { 43if ( front == back ) 44return false; Dequeue continued… Returns false if client tries to dequeue an empty queue.

101 101 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header

102 102 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header

103 103 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr

104 104 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr

105 105 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr deqElement: passed in by reference

106 106 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr deqElement:

107 107 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr deqElement:

108 108 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr deqElement:

109 109 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr deqElement:

110 110 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr deqElement:

111 111 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr Let’s consider what happens if only one node is left to dequeue.

112 112 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header Let’s consider what happens if only one node is left to dequeue.

113 113 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header

114 114 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr

115 115 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr

116 116 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr deqElement:

117 117 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr deqElement:

118 118 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr deqElement:

119 119 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr deqElement:

120 120 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front back header ptr deqElement:

121 121 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front header ptr deqElement: back

122 122 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front header ptr deqElement: back

123 123 Dequeue (cont.) 45Node *ptr = front->next; 46deqElement = ptr->info; 47front->next = ptr->next; 48if ( back == ptr ) 49back = front; 50delete ptr; 51 52return true; 53 } front header ptr deqElement: back

124 124 Peek 54 template 55 bool Queue ::peek( 56DataType & frontElement ) 57 { 58if ( front == back ) 59return false; 60frontElement = front->next->info; 61return true; 62 }

125 125 isEmpty and makeEmpty 63 template 64 bool Queue ::isEmpty( ) const 65 { 66 return front == back; 67 } 68 69 template 70 void Queue ::makeEmpty( ) 71 { 72 DataType temp; 73while ( dequeue( temp ) ); 74 }

126 126 deepCopy 75 template 76 inline void Queue ::deepCopy( 77const Queue & original ) 78 { 79Node *copyptr = front = &header; 80Node *originalptr = original.front; frontback OriginalCopy header

127 127 deepCopy 75 template 76 inline void Queue ::deepCopy( 77const Queue & original ) 78 { 79Node *copyptr = front = &header; 80Node *originalptr = original.front; frontback OriginalCopy header

128 128 deepCopy 75 template 76 inline void Queue ::deepCopy( 77const Queue & original ) 78 { 79Node *copyptr = front = &header; 80Node *originalptr = original.front; frontback OriginalCopy header front copyptr

129 129 deepCopy 75 template 76 inline void Queue ::deepCopy( 77const Queue & original ) 78 { 79Node *copyptr = front = &header; 80Node *originalptr = original.front; frontback OriginalCopy header front copyptr

130 130 deepCopy 75 template 76 inline void Queue ::deepCopy( 77const Queue & original ) 78 { 79Node *copyptr = front = &header; 80Node *originalptr = original.front; frontback OriginalCopy header front originalptrcopyptr

131 131 deepCopy 75 template 76 inline void Queue ::deepCopy( 77const Queue & original ) 78 { 79Node *copyptr = front = &header; 80Node *originalptr = original.front; frontback OriginalCopy header front originalptrcopyptr deepCopy function continued…

132 132 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

133 133 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

134 134 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

135 135 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

136 136 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

137 137 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

138 138 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

139 139 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

140 140 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

141 141 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

142 142 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

143 143 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

144 144 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

145 145 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

146 146 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

147 147 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

148 148 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

149 149 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

150 150 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

151 151 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

152 152 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

153 153 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

154 154 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

155 155 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

156 156 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

157 157 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

158 158 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

159 159 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

160 160 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr

161 161 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr back

162 162 deepCopy (cont.) 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } frontback OriginalCopy header front originalptrcopyptr back Let’s consider the empty case…

163 163 deepCopy (cont.) 75 template 76 inline void Queue ::deepCopy( 77const Queue & original ) 78 { 79Node *copyptr = front = &header; 80Node *originalptr = original.front; frontback OriginalCopy header

164 164 deepCopy (cont.) 75 template 76 inline void Queue ::deepCopy( 77const Queue & original ) 78 { 79Node *copyptr = front = &header; 80Node *originalptr = original.front; frontback Original header Copy header front copyptr

165 165 deepCopy (cont.) 75 template 76 inline void Queue ::deepCopy( 77const Queue & original ) 78 { 79Node *copyptr = front = &header; 80Node *originalptr = original.front; frontback Original header Copy header front copyptr

166 166 deepCopy (cont.) 75 template 76 inline void Queue ::deepCopy( 77const Queue & original ) 78 { 79Node *copyptr = front = &header; 80Node *originalptr = original.front; frontback Original header Copy header front copyptr originalptr

167 167 deepCopy (cont.) 75 template 76 inline void Queue ::deepCopy( 77const Queue & original ) 78 { 79Node *copyptr = front = &header; 80Node *originalptr = original.front; frontback Original header Copy header front copyptr originalptr

168 168 deepCopy (cont.) frontback Original header Copy header front copyptr originalptr 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 }

169 169 deepCopy (cont.) frontback Original header Copy header front copyptr originalptr 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 }

170 170 deepCopy (cont.) frontback Original header Copy header front copyptr originalptr 81while ( originalptr != original.back ) { 82originalptr = originalptr->next; 83copyptr->next = new Node ; 84copyptr = copyptr->next; 85copyptr->info = originalptr->info; 86} 87back = copyptr; 88 } back

171 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 172 Enqueue / Dequeue 0 1 2 3 4 5 6 7 frontback

173 173 0 1 2 3 4 5 6 7 frontback DEQUEUE Enqueue / Dequeue (cont.)

174 174 0 1 2 3 4 5 6 7 frontback DEQUEUE Enqueue / Dequeue (cont.)

175 175 0 1 2 3 4 5 6 7 frontback DEQUEUE Enqueue / Dequeue (cont.)

176 176 0 1 2 3 4 5 6 7 frontback DEQUEUE Enqueue / Dequeue (cont.)

177 177 0 1 2 3 4 5 6 7 frontback ENQUEUE Enqueue / Dequeue (cont.)

178 178 0 1 2 3 4 5 6 7 frontback ENQUEUE Enqueue / Dequeue (cont.)

179 179 0 1 2 3 4 5 6 7 frontback ENQUEUE Enqueue / Dequeue (cont.)

180 180 0 1 2 3 4 5 6 7 frontback ENQUEUE Enqueue / Dequeue (cont.)

181 181 0 1 2 3 4 5 6 7 frontback DEQUEUE Enqueue / Dequeue (cont.)

182 182 0 1 2 3 4 5 6 7 frontback DEQUEUE Enqueue / Dequeue (cont.)

183 183 0 1 2 3 4 5 6 7 frontback DEQUEUE Enqueue / Dequeue (cont.)

184 184 0 1 2 3 4 5 6 7 frontback DEQUEUE Enqueue / Dequeue (cont.)

185 185 0 1 2 3 4 5 6 7 frontback ENQUEUE Enqueue / Dequeue (cont.)

186 186 0 1 2 3 4 5 6 7 frontback ENQUEUE Enqueue / Dequeue (cont.)

187 187 0 1 2 3 4 5 6 7 frontback DEQUEUE Enqueue / Dequeue (cont.)

188 188 0 1 2 3 4 5 6 7 frontback DEQUEUE Enqueue / Dequeue (cont.)

189 189 0 1 2 3 4 5 6 7 frontback DEQUEUE Enqueue / Dequeue (cont.)

190 190 0 1 2 3 4 5 6 7 frontback ENQUEUE Enqueue / Dequeue (cont.)

191 191 0 1 2 3 4 5 6 7 frontback ENQUEUE ? Enqueue / Dequeue (cont.)

192 192 0 1 2 3 4 5 6 7 frontback ENQUEUE Enqueue / Dequeue (cont.) We could double the size of the array here.

193 193 0 1 2 3 4 5 6 7 frontback 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 194 0 1 2 3 4 5 6 7 frontback ENQUEUE Enqueue / Dequeue (cont.) We handle this problem by having the back wrap around to the beginning of the array.

195 195 0 1 2 3 4 5 6 7 frontback ENQUEUE Enqueue / Dequeue (cont.)

196 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 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 198 A Full Array 0 1 2 3 4 5 6 7 frontback

199 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 200 The Queue Class Template 1 #include "Array.h" 2 3 template 4 class Queue 5 { 6 public: 7 Queue( ); 8void enqueue( DataType element ); 9bool dequeue( DataType & deqElement ); 10bool peek( DataType & frontElement ); 11bool isEmpty( ) const; 12void makeEmpty( );

201 201 The Queue Class Template (cont.) 13 private: 14Array elements; 15int front; 16int back; 17 }; 18 19 #include "queue.cpp"

202 202 Queue Constructor 1 // queue.cpp 2 template 3 Queue ::Queue( ) 4 : elements( 2 ), front( -1 ), back( -1 ) 5 { 6 }

203 203 Enqueue 7 template 8 void Queue ::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, readjust 14 if ( back < front ) { 15int i = elements.length( ) - 1; 16for ( int j = ((i + 1) >> 1) - 1; j >= front; i--, j-- ) 17elements[ i ] = elements[ j ]; 18front = i + 1; 19} 20} Enqueue continued…

204 204 Enqueue (cont.) 21if ( back == -1 ) // queue is empty 22front = 0; 23back = (back == elements.length( ) - 1)? 240 : back + 1; 25elements[ back ] = element; 26 }

205 205 Dequeue 27 template 28 bool Queue ::dequeue( 29DataType & deqElement ) 30 { 31if (front == -1 ) 32return false; Dequeue continued…

206 206 Dequeue (cont.) 33deqElement = elements[ front ]; 34if ( front == back ) // only one element was in queue 35front = back = -1; 36else 37front = (front == elements.length( ) - 1)? 380 : front + 1; Dequeue continued…

207 207 Dequeue (cont.) 39// try to reduce the size of the array 40int trysize = elements.length( ); 41int numElements = (front <= back)? 42back - front + 1 : back + trysize - front + 1; 43while ( ( numElements > 2 ) && trysize > 2 ) 44trysize >>= 1; Dequeue continued…

208 208 Dequeue (cont.) 45if ( trysize < elements.length( ) ) { 46// readjust so we won't lose elements when 47// shrinking the array size 48int i, j; 49if ( 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 209 Dequeue (cont.) 50 for ( i = trysize - 1, j = elements.length( ) - 1; j >= front; i--, j-- ) 51elements[ i ] = elements[ j ]; 52 front = i + 1; 53 try { 54elements.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 210 Dequeue (cont.) 61return true; 62} 63else if ( front = trysize ) { 64for ( i = 0, j = front; j <= back; i++, j++ ) 65elements[ i ] = elements[ j ]; 66front = 0; 67back = 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 211 Dequeue (cont.) 69try { 70elements.changeSize( trysize ); 71 } 72catch( … ) { } 73} 74 75return true; 76 } This changeSize attempt handles the “front = trysize” case AND the case where no realignment is necessary: “front <= back && back < trysize”

212 212 Peek 77 template 78 bool Queue ::peek( 79DataType & frontElement ) 80 { 81if (front == -1 ) 82return false; 83frontElement = elements[ front ]; 84return true; 85 }

213 213 isEmpty 86 template 87 bool Queue ::isEmpty( ) const 88 { 89return front == -1; 90 }

214 214 makeEmpty 91 template 92 void Queue ::makeEmpty( ) 93 { 94front = back = -1; 95try { 96elements.changeSize( 2 ); 97} 98catch( … ) { } 99 }


Download ppt "1 C++ Classes and Data Structures Jeffrey S. Childs Chapter 8 Stacks and Queues Jeffrey S. Childs Clarion University of PA © 2008, Prentice Hall."

Similar presentations


Ads by Google