Dynamic Arrays and Stacks Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University.

Slides:



Advertisements
Similar presentations
Stacks.
Advertisements

Chapter 5.
Queues 4/14/2017 5:24 PM 5.2 Queues Queues Dr Zeinab Eid.
Elementary Data Structures CS 110: Data Structures and Algorithms First Semester,
Today’s Agenda  Stacks  Queues  Priority Queues CS2336: Computer Science II.
Stacks. 2 Outline and Reading The Stack ADT (§4.2.1) Applications of Stacks (§4.2.3) Array-based implementation (§4.2.2) Growable array-based stack.
© 2004 Goodrich, Tamassia Stacks. © 2004 Goodrich, Tamassia Stacks2 The Stack ADT (§4.2) The Stack ADT stores arbitrary objects Insertions and deletions.
© 2004 Goodrich, Tamassia Stacks. © 2004 Goodrich, Tamassia Stacks2 Abstract Data Types (ADTs) An abstract data type (ADT) is an abstraction of a data.
Stacks, Queues, and Deques
Stacks. 2 Outline and Reading The Stack ADT (§2.1.1) Array-based implementation (§2.1.1) Growable array-based stack (§1.5) Java.util.Stack class Java.util.Vector.
Part-B1 Stacks. Stacks2 Abstract Data Types (ADTs) An abstract data type (ADT) is an abstraction of a data structure An ADT specifies: Data stored Operations.
Part-B1 Stacks. Stacks2 Abstract Data Types (ADTs) An abstract data type (ADT) is an abstraction of a data structure An ADT specifies: Data stored Operations.
CHAPTER 6 Stacks Array Implementation. 2 Stacks A stack is a linear collection whose elements are added and removed from one end The last element to be.
Andreas Klappenecker [based on the slides of Prof. Welch]
Stacks. 2 Outline and Reading The Stack ADT (§2.1.1) Applications of Stacks (§2.1.1) Array-based implementation (§2.1.1) Growable array-based stack (§1.5)
EXPANDING STACKS AND QUEUES CS16: Introduction to Data Structures & Algorithms 1 Tuesday, February 10, 2015.
Object Oriented Data Structures
Stacks. week 2a2 Outline and Reading The Stack ADT (§4.1) Applications of Stacks Array-based implementation (§4.1.2) Growable array-based stack Think.
Implementing Stacks Ellen Walker CPSC 201 Data Structures Hiram College.
Stacks. 2 What Are Stacks ? PUSHPOP 0 MAX Underflow Overflow.
CHAPTER 05 Compiled by: Dr. Mohammad Omar Alhawarat Stacks & Queues.
Abstract Data Type (ADT) & Stacks
Stacks and Linked Lists. Abstract Data Types (ADTs) An ADT is an abstraction of a data structure that specifies – Data stored – Operations on the data.
1 CSC 222: Computer Programming II Spring 2004 Pointers and linked lists  human chain analogy  linked lists: adding/deleting/traversing nodes  Node.
Stacks 1. Stack  What is a stack? An ordered list where insertions and deletions occur at one end called the top. Also known as last-in-first-out (LIFO)
COP3530 Data Structures600 Stack Stack is one the most useful ADTs. Like list, it is a collection of data items. Supports “LIFO” (Last In First Out) discipline.
Chapter 13 Recursion. Learning Objectives Recursive void Functions – Tracing recursive calls – Infinite recursion, overflows Recursive Functions that.
© 2004 Goodrich, Tamassia Stacks. © 2004 Goodrich, Tamassia Stacks2 Abstract Data Types (ADTs) An abstract data type (ADT) is an abstraction of a data.
Stacks. A stack is a data structure that holds a sequence of elements and stores and retrieves items in a last-in first- out manner (LIFO). This means.
General Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University of Wisconsin.
30 May Stacks (5.1) CSE 2011 Winter Stacks2 Abstract Data Types (ADTs) An abstract data type (ADT) is an abstraction of a data structure An.
Linked Lists part 2 CS 244 Brent M. Dingle, Ph.D. Game Design and Development Program Department of Mathematics, Statistics, and Computer Science University.
Dynamic Arrays and Stacks CS 244 Brent M. Dingle, Ph.D. Game Design and Development Program Department of Mathematics, Statistics, and Computer Science.
Min Chen School of Computer Science and Engineering Seoul National University Data Structure: Chapter 3.
Stacks and Queues. 2 3 Runtime Efficiency efficiency: measure of computing resources used by code. can be relative to speed (time), memory (space), etc.
Nyhoff, ADTs, Data Structures and Problem Solving with C++, Second Edition, © 2005 Pearson Education, Inc. All rights reserved Stacks.
Lecture6: Stacks Bohyung Han CSE, POSTECH CSED233: Data Structures (2014F)
Linked Lists part 1 CS 244 Brent M. Dingle, Ph.D. Game Design and Development Program Department of Mathematics, Statistics, and Computer Science University.
© 2004 Goodrich, Tamassia Vectors1 Vectors and Array Lists.
Array Lists1 © 2010 Goodrich, Tamassia. Array Lists2 The Array List ADT  The Array List ADT extends the notion of array by storing a sequence of arbitrary.
Merge Sort Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University of Wisconsin.
Parasol Lab, Dept. CSE, Texas A&M University
Chapter 5 Linked List by Before you learn Linked List 3 rd level of Data Structures Intermediate Level of Understanding for C++ Please.
Welcome to CSCE 221 – Data Structures and Algorithms
1 CSC 222: Computer Programming II Spring 2004 Stacks and recursion  stack ADT  push, pop, top, empty, size  vector-based implementation, library 
CH 5 : STACKS, QUEUES, AND DEQUES ACKNOWLEDGEMENT: THE SLIDES ARE PREPARED FROM SLIDES PROVIDED WITH DATA STRUCTURES AND ALGORITHMS IN C++, GOODRICH, TAMASSIA.
Lists1 © 2010 Goodrich, Tamassia. Position ADT  The Position ADT models the notion of place within a data structure where a single object is stored 
Computer Science Department Data Structure and Algorithms Lecture 3 Stacks.
Stack. ADS2 Lecture 1010 The Stack ADT (GoTa §5.1) The Stack ADT stores arbitrary objects Insertions and deletions follow the last-in.
Linked Lists Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University of Wisconsin.
1 Stacks Abstract Data Types (ADTs) Stacks Application to the analysis of a time series Java implementation of a stack Interfaces and exceptions.
Stacks Presentation for use with the textbook Data Structures and Algorithms in Java, 6 th edition, by M. T. Goodrich, R. Tamassia, and M. H. Goldwasser,
Stacks (and Queues).
Lists and Iterators 5/3/2018 Presentation for use with the textbook Data Structures and Algorithms in Java, 6th edition, by M. T. Goodrich, R. Tamassia,
Stacks Stacks.
CSCI 3333 Data Structures Stacks.
Stacks.
Queues Queues Queues.
More on Merge Sort CS 244 This presentation is not given in class
Lists and Iterators 3/9/15 Presentation for use with the textbook Data Structures and Algorithms in Java, 6th edition, by M. T. Goodrich, R. Tamassia,
Vectors 11/23/2018 1:03 PM Growing Arrays Vectors.
Stacks.
" A list is only as strong as its weakest link. " - Donald Knuth
Array-Based Sequences
Stacks 12/7/2018 Presentation for use with the textbook Data Structures and Algorithms in Java, 6th edition, by M. T. Goodrich, R. Tamassia, and M. H.
Cs212: Data Structures Computer Science Department Lecture 6: Stacks.
Copyright © Aiman Hanna All rights reserved
Vectors and Array Lists
Stacks and Linked Lists
Presentation transcript:

Dynamic Arrays and Stacks Data Structures and Algorithms CS 244 Brent M. Dingle, Ph.D. Department of Mathematics, Statistics, and Computer Science University of Wisconsin – Stout Based on the book: Data Structures and Algorithms in C++ (Goodrich, Tamassia, Mount) Some content from Data Structures Using C++ (D.S. Malik)

Points of Note Assignment 7 is posted Due soon: Wednesday, April 2 Assignment 8 is posted Due Thursday, April 3 Assignment 9 is posted Due Thursday, April 10

Previously Talked about Dynamic Arrays With a Pitcher Example

Today Stacks – Chapter 5 What are they? How are the used? How can we implement them Static Array Dynamic Array Amortized Time Linked Lists

Marker Slide Any General Questions ? Next up Stacks Optional: Magic Trick Description Application STATIC Array Based DYNAMIC Array Based Amortization Description Applied to Incremental Increase for Dynamic Array Resizing Applied to Doubling Increase for Dynamic Array Resizing Stack Implementation Analysis Static Array versus Dynamic Array Linked List Refresher Stack Implemented as a Linked List

Optional: Begin with a “Magic” Trick Pick a card from 15 Put card back Deal the 15 cards into 3 columns (stacks) Identify the column containing the card Pick up into 1 stack and repeat (2 times) The eighth card will now be the selected card How? Why?

Optional: Group Work – Duplicate and Explain Create an explanation of why it works Try doing it wrong Note the importance of STACKS How do you pick up the columns (stacks) and why? How do you deal out the cards to make the columns and why? Note the relationship of the numbers and the math behind it Why 3 stacks? Why 15 cards? Why deal them out 3 times? Does it work with other numbers of cards? Try 9? Try 12? Pick a card from 15 Put card back Deal the 15 cards into 3 columns (stacks) Identify the column containing the card Pick up into 1 stack and repeat (2 times) The eighth card will now be the selected card How? Why?

Marker Slide Questions on: Stacks Optional: Magic Trick Next up Description Application STATIC Array Based DYNAMIC Array Based Amortization Description Applied to Incremental Increase for Dynamic Array Resizing Applied to Doubling Increase for Dynamic Array Resizing Stack Implementation Analysis Static Array versus Dynamic Array Linked List Refresher Stack Implemented as a Linked List

Marker Slide Questions? Next up Description Application STATIC Array Based DYNAMIC Array Based Amortization Description Applied to Incremental Increase for Dynamic Array Resizing Applied to Doubling Increase for Dynamic Array Resizing Stack Implementation Analysis Static Array versus Dynamic Array Linked List Refresher Stack Implemented as a Linked List

Stack Intro We are now to chapter 5 of the book Unit 2 on D2L You are now all assumed to be proficient at C++ and familiar with the processes needed to analyze algorithms using Big-Oh notation We may still review from time to time We will be discussing Stacks today As an ADT – what are they? Using Static Arrays to implement the Stack ADT Using Dynamic Arrays to implement the Stack ADT Using Linked Lists to implement the Stack ADT

Stacks

Stacks store arbitrary objects (Pez in this case)

Stacks Stacks store arbitrary objects (Pez in this case) Operations – push(e): inserts an element to the top of the stack

Stacks Stacks store arbitrary objects (Pez in this case) Operations – push(e): inserts an element to the top of the stack

Stacks Stacks store arbitrary objects (Pez in this case) Operations – push(e): inserts an element to the top of the stack – pop(): removes and returns the top element of the stack

Stacks Stacks store arbitrary objects (Pez in this case) Operations – push(e): inserts an element to the top of the stack – pop(): removes and returns the top element of the stack

Stacks Stacks store arbitrary objects (Pez in this case) Operations – push(e): inserts an element to the top of the stack – pop(): removes and returns the top element of the stack

Stacks Stacks store arbitrary objects (Pez in this case) Operations – push(e): inserts an element to the top of the stack – pop(): removes and returns the top element of the stack – top(): returns a reference to the top element of the stack, but doesn’t remove it

Stacks Stacks store arbitrary objects (Pez in this case) Operations – push(e): inserts an element to the top of the stack – pop(): removes and returns the top element of the stack – top(): returns a reference to the top element of the stack, but doesn’t remove it Optional operations – size(): returns the number of elements in the stack – empty(): returns a bool indicating if the stack contains any objects

Stack Exceptions Attempting to execute an operation of ADT may cause an error condition called an exception Exceptions are said to be “thrown” by an operation that cannot be executed In the Stack ADT, pop and top cannot be performed if the stack is empty Attempting to execute pop or top on an empty stack throws an EmptyStackException

Class Exercise: Stacks Describe the output and final structure of the stack after the following operations: Push(8) Push(3) Pop() Push(2) Push(5) Pop() Push(9) Push(1)

Marker Slide Questions on: Stacks Description Next up Application STATIC Array Based DYNAMIC Array Based Amortization Description Applied to Incremental Increase for Dynamic Array Resizing Applied to Doubling Increase for Dynamic Array Resizing Stack Implementation Analysis Static Array versus Dynamic Array Linked List Refresher Stack Implemented as a Linked List

So far Stacks A stack is an ordered collection of entries that can be accessed only at one end (the top of the stack) Common place examples: pancakes, plates, trays Items in a stack must be removed in the reverse order that they were added to the stack This is referred to as a Last-In/First Out (LIFO) structure

Other Applications of Stacks Direct Applications Visited Page history of a web-browser Undo sequence in a text editor Saving local variables when one function calls another, and that one calls yet another, and… Indirect Applications Auxiliary data structure for algorithms Component of other data structures

C++ Run-time Stack The C++ run-time system keeps track of the chain of active functions with a stack When a function is called, the run-time system pushes on the stack a frame containing Local variables and return value Program counter, keeping track of the statement being executed When a function returns, its frame is popped from the stack and control is passed to the method on top of the stack main() { int i; i = 5; foo(i); } foo(int j) { int k; k = j+1; bar(k); } bar(int m) { … }

C++ Run-time Stack The C++ run-time system keeps track of the chain of active functions with a stack When a function is called, the run-time system pushes on the stack a frame containing Local variables and return value Program counter, keeping track of the statement being executed When a function returns, its frame is popped from the stack and control is passed to the method on top of the stack main() { int i; i = 5; foo(i); } foo(int j) { int k; k = j+1; bar(k); } bar(int m) { … } main PC = 2 i = 5

C++ Run-time Stack The C++ run-time system keeps track of the chain of active functions with a stack When a function is called, the run-time system pushes on the stack a frame containing Local variables and return value Program counter, keeping track of the statement being executed When a function returns, its frame is popped from the stack and control is passed to the method on top of the stack main() { int i; i = 5; foo(i); } foo(int j) { int k; k = j+1; bar(k); } bar(int m) { … } main PC = 2 i = 5 foo PC = 3 j = 5 k = 6

C++ Run-time Stack The C++ run-time system keeps track of the chain of active functions with a stack When a function is called, the run-time system pushes on the stack a frame containing Local variables and return value Program counter, keeping track of the statement being executed When a function returns, its frame is popped from the stack and control is passed back to the function that called it main() { int i; i = 5; foo(i); } foo(int j) { int k; k = j+1; bar(k); } bar(int m) { … } main PC = 2 i = 5 foo PC = 3 j = 5 k = 6

C++ Run-time Stack The C++ run-time system keeps track of the chain of active functions with a stack When a function is called, the run-time system pushes on the stack a frame containing Local variables and return value Program counter, keeping track of the statement being executed When a function returns, its frame is popped from the stack and control is passed back to the function that called it main() { int i; i = 5; foo(i); } foo(int j) { int k; k = j+1; bar(k); } bar(int m) { … } main PC = 2 i = 5

Marker Slide Questions on: Stacks Description Application Next up STATIC Array Based DYNAMIC Array Based Amortization Description Applied to Incremental Increase for Dynamic Array Resizing Applied to Doubling Increase for Dynamic Array Resizing Stack Implementation Analysis Static Array versus Dynamic Array Linked List Refresher Stack Implemented as a Linked List

(static) Array-based Stack A simple way of implementing the Stack ADT uses an array We add elements from left to right A variable keeps track of the index of the top element S 012 t … Algorithm size() return t + 1 Algorithm empty() return size () == 0 Algorithm pop() if empty() then throw EmptyStackException else t  t  1 return S[t + 1]

(static) Array-based Stack A simple way of implementing the Stack ADT uses an array We add elements from left to right A variable keeps track of the index of the top element S 012 t … Algorithm size() return t + 1 Algorithm empty() return size () == 0 Algorithm pop() if empty() then throw EmptyStackException else t  t  1 return S[t + 1]

(static) Array-based Stack A simple way of implementing the Stack ADT uses an array We add elements from left to right A variable keeps track of the index of the top element S 012 t … Algorithm size() return t + 1 Algorithm empty() return size () == 0 Algorithm pop() if empty() then throw EmptyStackException else t  t  1 return S[t + 1]

(static) Array-based Stack The array storing the stack elements may become full A push operation will then throw a FullStackException Limitation of the array-based implementation Not intrinsic to the Stack ADT S 012 t … Algorithm push(e) if t = S.length  1 then throw FullStackException else t  t + 1 S[t]  e

Performance and Limitations (array-based implementation of stack ADT) Performance – Let n be the number of elements in the stack – The space used is O(n) – Each operation (push, pop, top, size, empty) runs in time O(1) Limitations – The maximum size of the stack must be defined a priori, and cannot be changed – Trying to push a new element onto a full stack causes an implementation-specific exception

General Stack Interface in C++ Requires the definition of a class EmptyStackException Most similar in STL to std::vector template class Stack { public: int size(); bool isEmpty(); Type& top() throw(EmptyStackException); void push(Type e); Type pop() throw(EmptyStackException); };

template class ArrayStack { private: int capacity;// stack capacity Type *S;// stack array int top;// top of stack public: ArrayStack(int c) : capacity(c) { S = new Type [capacity]; top = -1; } bool isEmpty() { return top < 0; } Type pop() throw(EmptyStackException) { if ( isEmpty() ) throw EmptyStackException("Popping from empty stack"); return S[ top-- ]; } //… (other functions omitted) Array-based Stack in C++

Stacks – Fun Application Word Reversal LOVE becomes EVOL Useful for finding palindromes "Radar" becomes "radaR" "Step on no Pets" becomes "steP on no petS" Sidetrack

Math Check – Application Stacks are often used for evaluating math formulas For example checking for matching parentheses ( ( x + y * ( z + 7 ) ) * (a + b) ) Processing the line left to right Each open paren, (, equates to a push Each closed paren, ), is a pop If matched the stack is empty at the end Sidetrack

2 Challenges Individually Write a program to print out the characters of a char array in reverse order by using a stack OR Write a program to check if the parentheses in a math string are balanced by using a stack Details on following slide Sidetrack

Challenges – Pick 1 Submit the code to DS15 – Static Stack drop box ONE.cpp file should be all you need NOT GROUP For possible extra credit on an assignment You have until before midnight tonight to finish #include #include // C version of string functions // - for strcpy, strlen using namespace std; const int MAX_WORDSIZE = 300; const int MAX_STACKSIZE = MAX_WORDSIZE; int pushChar(char ch); // function prototypes char popChar(); bool stackEmpty(); char g_stack[MAX_STACKSIZE]; // global vars int g_topIndex = -1; // “g_” for global int main() { char word[MAX_WORDSIZE]; // use a C function to copy a word into char array strcpy(word, "Bobby Socks"); cout << "Original word = " << word << endl; for (unsigned int i=0; i < strlen(word); i++) { : stuff you put in goes here int pushChar(char ch) { int retVal = 0; // default to fail if (g_topIndex+1 < MAX_STACKSIZE) { ++g_topIndex; g_stack[g_topIndex] = ch; retVal = 1; // success } return retVal; } char popChar() { char retVal = '\0'; if (g_topIndex >= 0) { retVal = g_stack[g_topIndex]; --g_topIndex; } return retVal; } bool stackEmpty() { bool retVal = false; if (g_topIndex < 0) { retVal = true; } return retVal; } Or put an equation here like: "( ( x + y * ( z + 7 ) ) * (a + b) )"

Performance and Limitations (Static Array Implementation of Stack ADT) Performance – Let n be the number of elements in the stack – The space used is O(n) – Each operation (push, pop, top, size, empty) runs in time O(1) Limitations – The maximum size of the stack must be defined a priori, and cannot be changed – Trying to push a new element onto a full stack causes an implementation-specific exception Back on Track

End Static – Begin Dynamic Static arrays can be used to implement stacks But have limitations (previous slide) Perhaps Dynamic Arrays will be better

Marker Slide Questions on: Stacks Description Application STATIC Array Based Next up DYNAMIC Array Based Amortization Description Applied to Incremental Increase for Dynamic Array Resizing Applied to Doubling Increase for Dynamic Array Resizing Stack Implementation Analysis Static Array versus Dynamic Array Linked List Refresher Stack Implemented as a Linked List

Dynamic (growable) Array-based Stack In a push operation, when the array is full, instead of throwing an exception, we can replace the array with a larger one How large should the new array be? incremental strategy: increase the size by a constant c doubling strategy: double the size Algorithm push(e) if t = S.length  1 then A  new array of size … for i  0 to t do A[i]  S[i] S  A t  t + 1 S[t]  o Did we see these options before? With c = 2

So which will be better? Incremental Strategy Increasing the array size by a constant c Doubling Strategy Doubling the array size The answer is found using amortized time Did we see these options before? With c = 2

Marker Slide Questions on: Stacks Description Application STATIC Array Based DYNAMIC Array Based Next up Amortization Description Applied to Incremental Increase for Dynamic Array Resizing Applied to Doubling Increase for Dynamic Array Resizing Stack Implementation Analysis Static Array versus Dynamic Array Linked List Refresher Stack Implemented as a Linked List

Amortization (common use) Amortization (definition) Any guesses at this?

Amortization (common use) Amortization (definition) The process of decreasing an amount over time This shows up in several places in “real life” Such as Home Loans Business Payments

Amortization (common use) Amortization (definition) The process of decreasing an amount over time Home Loans Amortization is the process by which loan principle decreases over the life of a loan A portion of the payment is applied towards principle and a portion is applied toward interest The “cost” is stretched out over time Each payment is paying a small amount of what would be a large payment if paid all at once

Amortization (common use) Amortization (definition) The process of decreasing an amount over time Home Loans Amortization is the process by which loan principle decreases over the life of a loan A portion of the payment is applied towards principle and a portion is applied toward interest The “cost” is stretched out over time Each payment is paying a small amount of what would be a large payment if paid all at once Business Amortization allocates a lump sum (payment) amount to different time periods

Amortization (CS concept) Back in Computer Science world Certain operations may be extremely costly BUT They cannot occur frequently enough to slow down the entire program The less costly operations far outnumber the costly one Thus over the long-term they are “paying back” the program over a number of iterations

Amortized Analysis Requires knowledge about the entire series of operations Usually where a state persists between operations Like the capacity of memory allocated The idea is the worst case operation can alter the state in such a way that the worst case cannot occur again for a “long” time thus amortizing its cost

Applying Amortization Analysis (aka Aggregate Analysis) Aggregate analysis determines the upper bound T(n) of the total cost of a sequence of n operations T(n) is what we have been calculating previously for our Big-Oh stuff Then the amortized cost is T(n) / n because we make “small payments” for the worst operation across each operation

Marker Slide Questions on: Stacks Description Application STATIC Array Based DYNAMIC Array Based Amortization Description Next up Amortization Applied to Incremental Increase for Dynamic Array Resizing Applied to Doubling Increase for Dynamic Array Resizing Stack Implementation Analysis Static Array versus Dynamic Array Linked List Refresher Stack Implemented as a Linked List

Dynamic Array-based Stack In a push operation, when the array is full, instead of throwing an exception, we can replace the array with a larger one How large should the new array be? incremental strategy: increase the size by a constant c (say c = 2) doubling strategy: double the size Algorithm push(e) if t = S.length  1 then A  new array of size … for i  0 to t do A[i]  S[i] S  A t  t + 1 S[t]  o Recall: Recall we used c = 2 for the Pitcher class

Apply to +2(incremental) vs. double We compare the incremental strategy and the doubling strategy by analyzing the total time T(n) needed to perform a series of n push operations. Assume we start with an empty stack represented by an array of size 1 We call the amortized time of a push operation: the average time taken by a push over the series of operations i.e. T(n) / n

Incremental Analysis Say our array grows to a final size of n Then this strategy replaces the array k = n/c times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) We start with an array of capacity 2 and size 0 (empty) Assume a call to push() takes time 1 unit  we will push n things one at a time so need n time Each time we go past our capacity (k = n/2 times) we will increase capacity by c = 2 And we will have to copy the stuff already in the array into the new array So 2 items the first time, 4 items the second, 6 items the third, 8 items the fourth … Assuming each item we copy requires time 1 unit So 2 units of time for 2 items, 4 units of times for 4 items, 6 units for 6 items, … We then have the need for … + 2*k units of time  total time = n *2 + 2*3 + 2*4 +…+2*k How do we know it will replace the array k = n/c times? Think: how many “groups of size c” are in a set of n things?  n/c

Incremental Analysis Say our array grows to a final size of n Then this strategy replaces the array k = n/c times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) We start with an array of capacity 2 and size 0 (empty) Assume a call to push() takes time 1 unit  we will push n things one at a time so need n time Each time we go past our capacity (k = n/2 times) we will increase capacity by c = 2 And we will have to copy the stuff already in the array into the new array So 2 items the first time, 4 items the second, 6 items the third, 8 items the fourth … Assuming each item we copy requires time 1 unit So 2 units of time for 2 items, 4 units of times for 4 items, 6 units for 6 items, … We then have the need for … + 2*k units of time  total time = n *2 + 2*3 + 2*4 +…+2*k How do we know it will replace the array k = n/c times? Think: how many “groups of size c” are in a set of n things?  n/c

Incremental Analysis Say our array grows to a final size of n Then this strategy replaces the array k = n/c times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) We start with an array of capacity 2 and size 0 (empty) Assume a call to push() takes time 1 unit  we will push n things one at a time so need n time Each time we go past our capacity (k = n/2 times) we will increase capacity by c = 2 And we will have to copy the stuff already in the array into the new array So 2 items the first time, 4 items the second, 6 items the third, 8 items the fourth … Assuming each item we copy requires time 1 unit So 2 units of time for 2 items, 4 units of times for 4 items, 6 units for 6 items, … We then have the need for … + 2*k units of time  total time = n *2 + 2*3 + 2*4 +…+2*k How do we know it will replace the array k = n/c times? Think: how many “groups of size c” are in a set of n things?  n/c

Incremental Analysis Say our array grows to a final size of n Then this strategy replaces the array k = n/c times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) We start with an array of capacity 2 and size 0 (empty) Assume a call to push() takes time 1 unit  we will push n things one at a time so need n time Each time we go past our capacity (k = n/2 times) we will increase capacity by c = 2 And we will have to copy the stuff already in the array into the new array So 2 items the first time, 4 items the second, 6 items the third, 8 items the fourth … Assuming each item we copy requires time 1 unit So 2 units of time for 2 items, 4 units of times for 4 items, 6 units for 6 items, … We then have the need for … + 2*k units of time  total time = n *2 + 2*3 + 2*4 +…+2*k

Incremental Analysis Say our array grows to a final size of n Then this strategy replaces the array k = n/c times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) We start with an array of capacity 2 and size 0 (empty) Assume a call to push() takes time 1 unit  we will push n things one at a time so need n time Each time we go past our capacity (k = n/2 times) we will increase capacity by c = 2 And we will have to copy the stuff already in the array into the new array So 2 items the first time, 4 items the second, 6 items the third, 8 items the fourth … Assuming each item we copy requires time 1 unit So 2 units of time for 2 items, 4 units of times for 4 items, 6 units for 6 items, … We then have the need for … + 2*k units of time  total time = n *2 + 2*3 + 2*4 +…+2*k

Incremental Analysis Say our array grows to a final size of n Then this strategy replaces the array k = n/c times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) We start with an array of capacity 2 and size 0 (empty) Assume a call to push() takes time 1 unit  we will push n things one at a time so need n time Each time we go past our capacity (k = n/2 times) we will increase capacity by c = 2 And we will have to copy the stuff already in the array into the new array So 2 items the first time, 4 items the second, 6 items the third, 8 items the fourth … Assuming each item we copy requires time 1 unit So 2 units of time for 2 items, 4 units of times for 4 items, 6 units for 6 items, … We then have the need … + 2*k units of time  total time = n *2 + 2*3 + 2*4 +…+2*k

Incremental Analysis Say our array grows to a final size of n Then this strategy replaces the array k = n/c times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) We start with an array of capacity 2 and size 0 (empty) Assume a call to push() takes time 1 unit  we will push n things one at a time so need n time Each time we go past our capacity (k = n/2 times) we will increase capacity by c = 2 And we will have to copy the stuff already in the array into the new array So 2 items the first time, 4 items the second, 6 items the third, 8 items the fourth … Assuming each item we copy requires time 1 unit So 2 units of time for 2 items, 4 units of times for 4 items, 6 units for 6 items, … We then have the need … + 2*k units of time  total time = n + 2*1 + 2*2 + 2*3 + 2*4 +…+2*k

Incremental Analysis Say our array grows to a final size of n Then this strategy replaces the array k = n/c times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) We start with an array of capacity 2 and size 0 (empty) Assume a call to push() takes time 1 unit  we will push n things one at a time so need n time Each time we go past our capacity (k = n/2 times) we will increase capacity by c = 2 And we will have to copy the stuff already in the array into the new array So 2 items the first time, 4 items the second, 6 items the third, 8 items the fourth … Assuming each item we copy requires time 1 unit So 2 units of time for 2 items, 4 units of times for 4 items, 6 units for 6 items, … We then have the need … + 2*k units of time  total time = n + 2*1 + 2*2 + 2*3 + 2*4 +…+2*k

Incremental Analysis Say our array grows to a final size of n Then this strategy replaces the array k = n/c times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n)  total time = n *2 + 2*3 + 2*4 +…+2*k but we were using c = 2 for that… now put the c back in total time = n + c + c*2 + c*3 + c*4 +…+ c*k Next we simplify

Incremental Analysis Say our array grows to a final size of n Then this strategy replaces the array k = n/c times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc.

Incremental Analysis Say our array grows to a final size of n Then this strategy replaces the array k = n/c times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc. n stays n, c*(k 2 + k)/2 = (c/2)*k 2 + k/2 => k 2

Incremental Analysis Say our array grows to a final size of n Then this strategy replaces the array k = n/c times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc. Substitute in n/c for k and simplify

Incremental Analysis Say our array grows to a final size of n Then this strategy replaces the array k = n/c times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc. = O( n 2 )

Incremental Analysis Say our array grows to a final size of n Then this strategy replaces the array k = n/c times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc. So … T(n) is O(n + k 2 ) = O(n + n 2 ) And the Amortized Time is T(n)/n = O( n 2 ) = O( n )

Summary So Far Amortized Analysis tells us Incremental Increase Method is O(n) Next we do similar for the Doubling Method

Marker Slide Questions on: Stacks STATIC Array Based DYNAMIC Array Based Amortization Description Applied to Incremental Increase for Dynamic Array Resizing Next up Amortization Applied to Doubling Increase for Dynamic Array Resizing Stack Implementation Analysis Static Array versus Dynamic Array Linked List Refresher Stack Implemented as a Linked List

Doubling Analysis Say our array grows to a final size of n Then this strategy replaces the array k = log 2 n times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) We start with an array of capacity 2 and size 0 (empty) Assume a call to push() takes time 1 unit  we will push n things one at a time so need n time Each time we go past our capacity (k = log 2 n times) we will double capacity And we will have to copy the stuff already in the array into the new array So 2 items the first time, 4 items the second, 8 items the third, 16 items the fourth … Assuming each item we copy requires time 1 unit So 2 units of time for 2 items, 4 units of times for 4 items, 6 units for 6 items, … We then have the need for … + 2 k units of time  total time = n … + 2 k Think on: How do we know it replaces the array k = lg n times ?

Doubling Analysis Say our array grows to a final size of n Then this strategy replaces the array k = log 2 n times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) We start with an array of capacity 2 and size 0 (empty) Assume a call to push() takes time 1 unit  we will push n things one at a time so need n time Each time we go past our capacity (k = log 2 n times) we will double capacity And we will have to copy the stuff already in the array into the new array So 2 items the first time, 4 items the second, 8 items the third, 16 items the fourth … Assuming each item we copy requires time 1 unit So 2 units of time for 2 items, 4 units of times for 4 items, 6 units for 6 items, … We then have the need for … + 2 k units of time  total time = n … + 2 k Think on: How do we know it replaces the array k = lg n times ? lg n is the number of times n can be divided by 2…

Doubling Analysis Say our array grows to a final size of n Then this strategy replaces the array k = log 2 n times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) We start with an array of capacity 2 and size 0 (empty) Assume a call to push() takes time 1 unit  we will push n things one at a time so need n time Each time we go past our capacity (k = log 2 n times) we will double capacity And we will have to copy the stuff already in the array into the new array So 2 items the first time, 4 items the second, 8 items the third, 16 items the fourth … Assuming each item we copy requires time 1 unit So 2 units of time for 2 items, 4 units of times for 4 items, 6 units for 6 items, … We then have the need for … + 2 k units of time  total time = n … + 2 k

Doubling Analysis Say our array grows to a final size of n Then this strategy replaces the array k = log 2 n times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) We start with an array of capacity 2 and size 0 (empty) Assume a call to push() takes time 1 unit  we will push n things one at a time so need n time Each time we go past our capacity (k = log 2 n times) we will double capacity And we will have to copy the stuff already in the array into the new array So 2 items the first time, 4 items the second, 8 items the third, 16 items the fourth … Assuming each item we copy requires time 1 unit So 2 units of time for 2 items, 4 units of times for 4 items, 6 units for 6 items, … We then have the need for … + 2 k units of time  total time = n … + 2 k

Doubling Analysis Say our array grows to a final size of n Then this strategy replaces the array k = log 2 n times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) We start with an array of capacity 2 and size 0 (empty) Assume a call to push() takes time 1 unit  we will push n things one at a time so need n time Each time we go past our capacity (k = log 2 n times) we will double capacity And we will have to copy the stuff already in the array into the new array So 2 items the first time, 4 items the second, 8 items the third, 16 items the fourth … Assuming each item we copy requires time 1 unit So 2 units of time for 2 items, 4 units of times for 4 items, 6 units for 6 items, … We then have the need for … + 2 k units of time  total time = n … + 2 k

Doubling Analysis Say our array grows to a final size of n Then this strategy replaces the array k = log 2 n times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) We start with an array of capacity 2 and size 0 (empty) Assume a call to push() takes time 1 unit  we will push n things one at a time so need n time Each time we go past our capacity (k = log 2 n times) we will double capacity And we will have to copy the stuff already in the array into the new array So 2 items the first time, 4 items the second, 8 items the third, 16 items the fourth … Assuming each item we copy requires time 1 unit So 2 units of time for 2 items, 4 units of times for 4 items, 6 units for 6 items, … We then have the need for … + 2 k units of time  total time = n … + 2 k

Doubling Analysis Say our array grows to a final size of n Then this strategy replaces the array k = log 2 n times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n)  total time = n … + 2 k

Doubling Analysis Say our array grows to a final size of n Then this strategy replaces the array k = log 2 n times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) Put into Summation Notation

Doubling Analysis Say our array grows to a final size of n Then this strategy replaces the array k = log 2 n times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) Simplify the Summation

Doubling Analysis Say our array grows to a final size of n Then this strategy replaces the array k = log 2 n times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) Take a 2 out

Doubling Analysis Say our array grows to a final size of n Then this strategy replaces the array k = log 2 n times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) Substitute lg n in for k

Doubling Analysis Say our array grows to a final size of n Then this strategy replaces the array k = log 2 n times The total time T(n) of a series of n push operations is proportional to n + c + 2c + 3c + 4c + … + kc Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n) Simplify

Doubling Analysis Say our array grows to a final size of n Then this strategy replaces the array k = log 2 n times The total time T(n) of a series of n push operations is proportional to. Since c is a constant T(n) is O(n + k 2 ) = O(n 2 ) Divide by T(n) by n The amortized time is O(n)  total time = n … + 2 k = 3n – 1 So T(n) is O(n) and the amortized time T(n) / n = O(n) / n = O( 1 )

Marker Slide Questions on: Stacks STATIC Array Based DYNAMIC Array Based Amortization Description Applied to Incremental Increase for Dynamic Array Resizing Applied to Doubling Increase for Dynamic Array Resizing Next up Stack Implementation Analysis Static Array versus Dynamic Array Linked List Refresher Stack Implemented as a Linked List

Conclusions of Analysis So what did we learn? If we use a dynamic array the amortized time for a push operation is O(1) Why do we care? … Recall next slide

Performance and Limitations (static array-based implementation of stack ADT) Performance – Let n be the number of elements in the stack – The space used is O(n) – Each operation (push, pop, top, size, empty) runs in time O(1) Limitations – The maximum size of the stack must be defined a priori, and cannot be changed – Trying to push a new element onto a full stack causes an implementation-specific exception Recall:

Performance and Limitations (static array-based implementation of stack ADT) Performance – Let n be the number of elements in the stack – The space used is O(n) – Each operation (push, pop, top, size, empty) runs in time O(1) Limitations – The maximum size of the stack must be defined a priori, and cannot be changed – Trying to push a new element onto a full stack causes an implementation-specific exception Recall: Dynamic Arrays clearly fix this … BUT…

Performance and Limitations (static array-based implementation of stack ADT) Performance – Let n be the number of elements in the stack – The space used is O(n) – Each operation (push, pop, top, size, empty) runs in time O(1) Limitations – The maximum size of the stack must be defined a priori, and cannot be changed – Trying to push a new element onto a full stack causes an implementation-specific exception Recall: Seemed to fail on this point

Performance and Limitations (static array-based implementation of stack ADT) Performance – Let n be the number of elements in the stack – The space used is O(n) – Each operation (push, pop, top, size, empty) runs in time O(1) Limitations – The maximum size of the stack must be defined a priori, and cannot be changed – Trying to push a new element onto a full stack causes an implementation-specific exception Recall: But dynamic arrays are good here too … per the amortized analysis of doubling the capacity

Conclusion: Implementing Stack Using Dynamic Array Using a Dynamic array to implement a stack meets the ADT specification requirements for a Stack Doing so does NOT limit the stack size like a static array Amortization Analysis is required to see how it is also an efficient way to implement a Stack Intuitively it is not necessarily obvious

Marker Slide Questions on: Stacks STATIC Array Based DYNAMIC Array Based Amortization Description Applied to Incremental Increase for Dynamic Array Resizing Applied to Doubling Increase for Dynamic Array Resizing Static Array versus Dynamic Array Next up Linked List Refresher head towards Stacks again Stack Implemented as a Linked List

Singly Linked List A singly linked list is a structure consisting of a sequence of nodes A singly linked list stores a pointer to the first node (head) and last (tail) Each node stores – element – link to the next node LeonardSheldonHowardRaj  head tail Review

Singly Linked List A singly linked list is a structure consisting of a sequence of nodes A singly linked list stores a pointer to the first node (head) and last (tail) Each node stores – element – link to the next node LeonardSheldonHowardRaj  head tail Review

Singly Linked List A singly linked list is a structure consisting of a sequence of nodes A singly linked list stores a pointer to the first node (head) and last (tail) Each node stores – element – link to the next node next elem node LeonardSheldonHowardRaj  head tail Review

Singly Linked List Node next elem node template class SLinkedListNode { public: Type elem; SLinkedListNode *next; }; LeonardSheldonHowardRaj  Review A singly linked list is a structure consisting of a sequence of nodes A singly linked list stores a pointer to the first node (head) and last (tail) Each node stores – element – link to the next node

Singly Linked List A singly linked list is a structure consisting of a sequence of nodes Operations – insertFront(e): inserts an element on the front of the list – removeFront(): returns and removes the element at the front of the list – insertBack(e): inserts an element on the back of the list – removeBack(): returns and removes the element at the end of the list Review Details of each of these operations was given in previously

Marker Slide Questions on: Stacks STATIC Array Based DYNAMIC Array Based Amortization Description Applied to Incremental Increase for Dynamic Array Resizing Applied to Doubling Increase for Dynamic Array Resizing Static Array versus Dynamic Array Linked List Refresher head towards Stacks again Next up Stack Implemented as a Linked List

So far Stacks implemented using Static Arrays Dynamic Arrays (also in the MiniStack homework) Next Linked Lists

Stack with a Singly Linked List CLAIM: We can implement a stack with a singly linked list The top element of the stack is the first node of the list The space used is O(n) and each operation of the Stack ADT takes O(1) time Demonstration of how follows  t nodes elements top

Stack and Singly Linked List Singly linked list Operations – insertFront(e): inserts an element on the front of the list – removeFront(): returns and removes the element at the front of the list – insertBack(e): inserts an element on the back of the list – removeBack(): returns and removes the element at the end of the list Stack Operations push(e): inserts an element to the top of the stack pop(): removes and returns the top element of the stack top(): returns a reference to the top element of the stack, but doesn’t remove it size(): returns the number of elements in the stack empty(): returns a bool indicating if the stack contains any objects Recall

Stack and Singly Linked List Singly linked list Operations – insertFront(e): inserts an element on the front of the list – removeFront(): returns and removes the element at the front of the list – insertBack(e): inserts an element on the back of the list – removeBack(): returns and removes the element at the end of the list Stack Operations push(e): inserts an element to the top of the stack pop(): removes and returns the top element of the stack top(): returns a reference to the top element of the stack, but doesn’t remove it size(): returns the number of elements in the stack empty(): returns a bool indicating if the stack contains any objects Top is the First Node

Stack and Singly Linked List Singly linked list Operations – insertFront(e): inserts an element on the front of the list – removeFront(): returns and removes the element at the front of the list – insertBack(e): inserts an element on the back of the list – removeBack(): returns and removes the element at the end of the list Stack Operations push(e): inserts an element to the top of the stack pop(): removes and returns the top element of the stack top(): returns a reference to the top element of the stack, but doesn’t remove it size(): returns the number of elements in the stack empty(): returns a bool indicating if the stack contains any objects

Stack and Singly Linked List Singly linked list Operations – insertFront(e): inserts an element on the front of the list – removeFront(): returns and removes the element at the front of the list – insertBack(e): inserts an element on the back of the list – removeBack(): returns and removes the element at the end of the list Stack Operations push(e): inserts an element to the top of the stack pop(): removes and returns the top element of the stack top(): returns a reference to the top element of the stack, but doesn’t remove it size(): returns the number of elements in the stack empty(): returns a bool indicating if the stack contains any objects

Stack and Singly Linked List Singly linked list Operations – insertFront(e): inserts an element on the front of the list – removeFront(): returns and removes the element at the front of the list – insertBack(e): inserts an element on the back of the list – removeBack(): returns and removes the element at the end of the list Stack Operations push(e): inserts an element to the top of the stack pop(): removes and returns the top element of the stack top(): returns a reference to the top element of the stack, but doesn’t remove it size(): returns the number of elements in the stack empty(): returns a bool indicating if the stack contains any objects

Stack and Singly Linked List Singly linked list Operations – insertFront(e): inserts an element on the front of the list – removeFront(): returns and removes the element at the front of the list Stack Operations push(e): inserts an element to the top of the stack pop(): removes and returns the top element of the stack top(): returns a reference to the top element of the stack, but doesn’t remove it size(): returns the number of elements in the stack empty(): returns a bool indicating if the stack contains any objects top() would require a minor alteration or addition to LinkedList very similar to removeFront()

Stack and Singly Linked List Singly linked list Operations – insertFront(e): inserts an element on the front of the list – removeFront(): returns and removes the element at the front of the list Stack Operations push(e): inserts an element to the top of the stack pop(): removes and returns the top element of the stack top(): returns a reference to the top element of the stack, but doesn’t remove it size(): returns the number of elements in the stack empty(): returns a bool indicating if the stack contains any objects size() and isEmpty() would require the addition of a counter that increments each time push() is called and decrements when pop() is called

Stack with a Singly Linked List CONCLUSION: We can implement a stack with a singly linked list The top element of the stack is the first node of the list The space used is O(n) and each operation of the Stack ADT takes O(1) time push, pop, top, size, empty each are O(1) time  t nodes elements top

Stack Summary Stack Operation Complexity for Different Implementations Array Fixed-Size Array Dynamic (doubling strategy) Singly Linked List Pop() O(1) Push(o)O(1)O(n) Worst Case O(1) Best Case O(1) Average Case O(1) Top()O(1) Size(), isEmpty()O(1)

The End For next time Read Chapter 5 Stacks and Queues