Stacks Chapter 8
Objectives In this chapter, you will: Learn about stacks Examine various stack operations Learn how to implement a stack as an array Learn how to implement a stack as a linked list Discover stack applications Learn how to use a stack to remove recursion C++ Programming: Program Design Including Data Structures, Fifth Edition3
Stacks Stack: list of homogenous elements –Addition and deletion occur only at one end, called the top of the stack –Example: in a cafeteria, the second tray can be removed only if first tray has been removed –Last in first out (LIFO) data structure Operations: –Push: to add an element onto the stack –Pop: to remove an element from the stack
Stacks Linear list. One end is called top. Other end is called bottom. Additions to and removals from the top end only. top bottom
Various types of stacks
Stack Of Cups Add a cup to the stack. bottom top C A B D E F Remove a cup from new stack. A stack is a LIFO list. bottom top C A B D E
The Abstract Class stack template class stack { public: virtual ~stack() {} virtual bool empty() const = 0; virtual int size() const = 0; virtual T& top() = 0; virtual void pop() = 0; virtual void push(const T& theElement) = 0; };
Derive From A Linear List Class Class arrayList Class chain
–stack top is either left end or right end of linear list –empty() => arrayList::empty() –size() => arrayList::size() –top() => get(0) or get(size() - 1) abcde Derive From arrayList
when top is left end of linear list –push(theElement) => insert(0, theElement) –pop() => erase(0) –use left end of list as top of stack abcde
Derive From arrayList –when top is right end of linear list push(theElement) => insert(size(), theElement) pop() => erase(size()-1) –use right end of list as top of stack abcde
Derive From Chain –stack top is either left end or right end of linear list –empty() => chain::empty() –size() => chain::size() abcde NULL firstNode
Derive From Chain abcde NULL firstNode – when top is left end of linear list top() => get(0) push(theElement) => insert(0, theElement) pop() => erase(0)
Derive From Chain abcde null firstNode – when top is right end of linear list top() => get(size() - 1) push(theElement) => insert(size(), theElement) pop() => erase(size()-1) use left end of list as top of stack
Derive From arrayList template class derivedArrayStack : private arrayList, public stack { public: // code for stack methods comes here };
Constructor derivedArrayStack(int initialCapacity = 10) : arrayList (initialCapacity) {}
empty() And size() bool empty() const {return arrayList ::empty();} int size() const {return arrayList ::size();} abcde
top() T& top() { if (arrayList ::empty()) throw stackEmpty(); return get(arrayList ::size() - 1); } abcde
push(theElement) void push(const T& theElement) {insert(arrayList ::size(), theElement);} abcde
pop() void pop() { if (arrayList ::empty()) throw stackEmpty(); erase(arrayList ::size() - 1); } abcde
template class derivedArrayStack : private arrayList,public stack { public: derivedArrayStack(int initialCapacity = 10) :arrayList (initialCapacity) {} bool empty() const {return arrayList ::empty();} int size() const {return arrayList ::size();} T& top() { if (arrayList ::empty()) throw stackEmpty(); return get(arrayList ::size() - 1); } void pop() { if (arrayList ::empty()) throw stackEmpty(); erase(arrayList ::size() - 1); } void push(const T& theElement) {insert(arrayList ::size(), theElement);} };
Evaluation Merits of deriving from arrayList –Code for derived class is quite simple and easy to develop. –Code is expected to require little debugging. –Code for other stack implementations such as a linked implementation are easily obtained. Just replace private arrayList with private chain For efficiency reasons we must also make changes to use the left end of the list as the stack top rather than the right end.
Code From Scratch Use a 1D array stack whose data type is T. –same as using array element in arrayList Use an int variable stackTop. –Stack elements are in stack[0:stackTop]. –Top element is in stack[stackTop]. –Bottom element is in stack[0]. –Stack is empty iff stackTop = -1. –Number of elements in stack is stackTop + 1.
Code From Scratch template class class arrayStack : public stack { public: // public methods come here private: int stackTop; // current top of stack int arrayLength; // stack capacity T *stack; // element array };
Constructor template arrayStack ::arrayStack(int initialCapacity) {// Constructor. if (initialCapacity < 1) {// code to throw an exception comes here } arrayLength = initialCapacity; stack = new T[arrayLength]; stackTop = -1; }
push(…) template void arrayStack ::push(const T& theElement) {// Add theElement to stack. if (stackTop == arrayLength - 1) {// code to double capacity coms here } // add at stack top stack[++stackTop] = theElement; } abcde top
pop() void pop() { if (stackTop == -1) throw stackEmpty(); stack[stackTop--].~T(); // destructor for T } abcde top
Linked Stack template class linkedStack : public stack { public: linkedStack(int initialCapacity = 10) {stackTop = NULL; stackSize = 0;} ~linkedStack(); bool empty() const {return stackSize == 0;} int size() const {return stackSize;} T& top() { if (stackSize == 0) throw stackEmpty(); return stackTop->element; } void pop(); void push(const T& theElement); private: chainNode * stackTop; // pointer to stack top int stackSize; // number of elements in stack };
Push() template void linkedStack ::push(const T& theElement) { stackTop = new chainNode (theElement, stackTop); stackSize++; }
Pop() template void linkedStack ::pop() {// Delete top element. if (stackSize == 0) throw stackEmpty(); chainNode * nextNode = stackTop->next; delete stackTop; stackTop = nextNode; stackSize--; }
Implement stack derivedArrayStack.h derivedLinkedStack.h arrayStack.h linkedStack.h
Stack in C++
Applications
Parentheses Matching (((a+b)*c+d-e)/(f+g)-(h+j)*(k-l))/(m-n) –Output pairs (u,v) such that the left parenthesis at position u is matched with the right parenthesis at v. (2,6) (1,13) (15,19) (21,25) (27,31) (0,32) (34,38) (a+b))*((c+d) –(0,4) –right parenthesis at 5 has no matching left parenthesis –(8,12) –left parenthesis at 7 has no matching right parenthesis
Parentheses Matching scan expression from left to right when a left parenthesis is encountered, add its position to the stack when a right parenthesis is encountered, remove matching position from stack
Example (((a+b)*c+d-e)/(f+g)-(h+j)*(k-l))/(m-n) 0 1 2
Example (((a+b)*c+d-e)/(f+g)-(h+j)*(k-l))/(m-n) 0 1 (2,6)
Example (((a+b)*c+d-e)/(f+g)-(h+j)*(k-l))/(m-n) 0 1 (2,6)(1,13) 15
Example (((a+b)*c+d-e)/(f+g)-(h+j)*(k-l))/(m-n) 0 1 (2,6)(1,13)(15,19) 21
Example (((a+b)*c+d-e)/(f+g)-(h+j)*(k-l))/(m-n) 0 1 (2,6)(1,13)(15,19)(21,25) 27
Example (((a+b)*c+d-e)/(f+g)-(h+j)*(k-l))/(m-n) 0 1 (2,6)(1,13)(15,19)(21,25)(27,31)(0,32) and so on
Homework 2.1 Write a program that look for matched pairs of parentheses and matched pairs of brackets ([]) and report a nesting problem. For example: in the string (a+[b*(c-d)+f]), the output should be (0,14),(3,13),(6,10).
Towers Of Hanoi/Brahma ABC gold disks to be moved from tower A to tower C each tower operates as a stack cannot place big disk on top of a smaller one
Towers Of Hanoi/Brahma 3-disk Towers Of Hanoi/Brahma A BC 1 2 3
Towers Of Hanoi/Brahma 3-disk Towers Of Hanoi/Brahma A BC 1 2 3
Towers Of Hanoi/Brahma 3-disk Towers Of Hanoi/Brahma A BC 123
Towers Of Hanoi/Brahma 3-disk Towers Of Hanoi/Brahma A BC 12 3
Towers Of Hanoi/Brahma 3-disk Towers Of Hanoi/Brahma A BC 12 3
Towers Of Hanoi/Brahma 3-disk Towers Of Hanoi/Brahma A BC 123
Towers Of Hanoi/Brahma 3-disk Towers Of Hanoi/Brahma A BC 1 2 3
Towers Of Hanoi/Brahma 3-disk Towers Of Hanoi/Brahma A BC disk moves
Recursive Solution ABC 1 n > 0 gold disks to be moved from A to C using B move top n-1 disks from A to B using C
Recursive Solution A BC 1 move top disk from A to C
Recursive Solution A BC 1 move top n-1 disks from B to C using A
Recursive Solution A BC 1 moves(n) = 0 when n = 0 moves(n) = 2*moves(n-1) + 1 = 2 n -1 when n > 0
Homework : Write a recursive version of program to solve n-disk Tower of Hanoi problem 2.2.2: determine the maximum number of disk you can solve using recursive and stack programs.
Rat In A Maze
Move order is: right, down, left, up Block positions to avoid revisit.
Rat In A Maze Move order is: right, down, left, up Block positions to avoid revisit.
Rat In A Maze Move backward until we reach a square from which a forward move is possible.
Rat In A Maze Move down.
Rat In A Maze Move left.
Rat In A Maze Move down.
Rat In A Maze Move backward until we reach a square from which a forward move is possible.
Rat In A Maze Move backward until we reach a square from which a forward move is possible. Move downward.
Rat In A Maze Move right. Backtrack.
Rat In A Maze Move downward.
Rat In A Maze Move right.
Rat In A Maze Move one down and then right.
Rat In A Maze Move one up and then right.
Rat In A Maze Move down to exit and eat cheese. Path from maze entry to current position operates as a stack.
Homework 2.3 (bonus) Implement the Rat in a maze
Homework 2 Due date: Feb 24