Lecture 13 Stacks PIC 10B Todd Wittman e Th ba J ab We P ars th Ga he rad ng eri a ad Sh ow wn rite Do w p Re i sh 5th C r 2 e t t s e Wa enac t Fir o M h S tom an do Ph e e Gr W mic os T ars The Stack Concept A stack is a list of data that follows 2 rules 1 Data can only be accessed by removing the top pop 2 A new data element can only be added to the top of the stack push This means that all data in the middle of the stack is hidden Star W ars Ex A stack of books The B o ok The Leia Princes s Diar ies A stack is called a LIFO data structure Last In First Out We ve actually encountered stacks before Portrait of the Artist as a Young Wookie d Bore of the s Ring 1 Vectors Are Bad Stacks Vectors have stack features because we are given the pop back and push back functions But vectors are more than stacks because they can access the middle v i Adding erasing from the back end of the vector should always be an O 1 operation But it isn t Vectors are built on dynamic arrays But a dynamic array has to allocate a fixed number of blocks int v new int 10 So how does a vector change its size Resizing Vectors The vector actually allocates a fixed number of sequential memory blocks This is called the vector capacity not to be confused with the vector size The capacity changes as the size grows int v new int 10 capacity 10 If we do a push back so that the a larger capacity is needed the vector does the following steps Allocate a new dynamic array with 50 more capacity int new v new int 15 Copy the elements from the old array into the new Delete the old array Note this is an O N operation So a vector push back is usually an O 1 operation but slows to linear O N time when we reach the current capacity 2 Vector Capacity The capacity is how many blocks the vector can store before it needs to reallocate memory We can look up v s capacity with v capacity Note that at all times v must satisfy v capacity v size The code below shows how capacity grows vector int v for int i 1 i 20 i int cap v capacity while v size cap v push back 42 cout v capacity endl Linked Lists Are Good Stacks Recall the two basic facts about linked lists 1 Linked lists are slow at looking up elements in the middle of the list Stacks are not allowed to look up data in the middle All information is processed at the top of the stack 2 Linked lists are fast at inserting and erasing only if we know exactly where to insert erase All pushing and popping is done at the top of the stack so we always know exactly where to the push pop 3 The Stack Node A stack need only be a singly linked list template typename T class StackNode public StackNode T value template typename T friend class Stack private T data StackNode T down data down template typename T StackNode T StackNode T value data value down NULL The Stack Class template typename T class Stack public Stack Stack bool isEmpty void push T value T pop private StackNode T top top 10 down 20 down 30 Note pop is not a void function It returns the value that was just popped off the top of the stack down NULL 4 Stack Constructor Destructor template typename T Stack T Stack top NULL template typename T bool Stack T isEmpty return top NULL template typename T Stack T Stack while isEmpty T temp pop Pushing Onto The Stack 5 To push on the stack we need to create a new node to store the given value Then we link it into the list and set this as the new top down top 10 down template typename T void Stack T push T value StackNode T newTop new StackNode T value newTop down top top newTop return 20 down 30 down NULL 5 Popping Off The Stack return 10 Recall we want the pop operation to return the value we just removed To pop off the stack we set the node below the top as the new top Then we can delete the old node and return its value top template typename T T Stack T pop T topValue top data StackNode T topPtr top top top down delete topPtr return topValue 10 down 20 down 30 down NULL A Simple Example int main Stack string s s push chewbacca s push yoda s push luke cout Pushed in order chewbacca yoda luke n cout Popped in LIFO order n while s isEmpty cout s pop n return 0 6 The Call Stack Stacks are inherent in the computer compiler interpreter architecture When running a program the program maintains a call stack to determine what order to run the functions in int main fun2 void fun2 fun1 void fun1 fun1 Every time a function is called it is pushed onto the stack fun2 When the function is done it is popped off the stack main We run the function at the stack s top until the stack is empty Recursion as Stack Operation We can extend the call stack concept to recursive functions A recursive function can be re written as a non recursive function using stacks factorial 0 int factorial int N if N 0 return 1 return N factorial N 1 factorial 1 factorial 2 factorial 3 int main cout factorial 5 return 0 factorial 4 factorial 5 main 7 Recursion as Stack Operation Recall our countUp function printed the numbers from 1 up to N in that order void countUp int N int main if N 0 return countUp 3 countUp N 1 return 0 cout N n return When a function is called push it onto stack More specifically push the part of the function that remains after it calls a function When we hit return statement pop it off and go to next function on top of stack Let s illustrate this process Balancing Parentheses Given a string with a mathematical expression check if the parentheses are balanced isBalanced 1 2 3 4 returns true isBalanced 1 2 3 4 returns false Every time we see a start push onto the stack Every time we see an end pop off the stack So the parentheses are not balanced if 1 We try to pop but the stack is empty 2 When we are done the stack is not empty 8 Balancing Parentheses bool isBalanced string expression stack char s for int i 0 i expression length i if expression i s push if expression i if s isEmpty return false else char c s pop if s isEmpty return false return true …
View Full Document