Stacked Deque Gordon College Adapted from Nyhoff ADTs

  • Slides: 52
Download presentation
Stacked Deque Gordon College Adapted from Nyhoff, ADTs, Data Structures and Problem Solving with

Stacked Deque Gordon College Adapted from Nyhoff, ADTs, Data Structures and Problem Solving with C++ 1

Introduction to Stacks • A stack is a last-in-first-out (LIFO) data structure • Adding

Introduction to Stacks • A stack is a last-in-first-out (LIFO) data structure • Adding an item – Referred to as pushing it onto the stack • Removing an item – Referred to as popping it from the stack 2

A Stack • Definition: – An ordered collection of data items – Can be

A Stack • Definition: – An ordered collection of data items – Can be accessed at only one end (the top) • Operations: – construct a stack (usually empty) – check if it is empty – Push: add an element to the top – Top: retrieve the top element – Pop: remove the top element 3

Stack STL specifics value_type size_type stack() stack(const stack&) stack& operator=(const stack&) bool empty() const

Stack STL specifics value_type size_type stack() stack(const stack&) stack& operator=(const stack&) bool empty() const size_type size() const value_type& top() const void push(const value_type&) void pop() (type constant within class) (default constructor) (copy constructor) (assignment operator) 4

Example Program • Consider a program to do base conversion of a number (from

Example Program • Consider a program to do base conversion of a number (from base ten to base two) • Program to accomplish this – Demonstrates push, pop, and top 5

#include <stack> #include <iostream> using namespace std; void convert(int arg) { stack<int> binary; while(arg>0)

#include <stack> #include <iostream> using namespace std; void convert(int arg) { stack<int> binary; while(arg>0) { binary. push(arg%2); arg /= 2; } cout << endl; while(!binary. empty()) { cout << binary. top(); binary. pop(); } cout << endl; } int main() { convert(101); return 0; } 6

Stack Programming Application Example • Use a stack ADT in a program that reads

Stack Programming Application Example • Use a stack ADT in a program that reads a string, one character at a time and determines whether the string contains balanced parentheses (for each left parentheses - there should be a right) 7

Deque double-ended queue (pronounced deck) - elements are ordered following a strict linear sequence.

Deque double-ended queue (pronounced deck) - elements are ordered following a strict linear sequence. Properties • Individual elements can be accessed by their position index. • Iteration over the elements can be performed in any order. • Elements can be efficiently added and removed from any of its ends (either the beginning or the end of the sequence). Like the vector in these ways - however not guaranteed to have all its elements in contiguous storage locations 8

Deque • For frequent insertion or removals of elements at positions other than the

Deque • For frequent insertion or removals of elements at positions other than the beginning or the end, deques perform worse and have less consistent iterators and references than lists. • Like a vector: – a sequence that supports random access to elements – constant time insertion and removal of elements at the end of the sequence – linear time insertion and removal of elements in the middle. • Not like a vector: – constant time insertion and removal of elements at the beginning of the sequence – nothing like capacity() and reserve() 9

STL Deque Iterators: begin Return iterator to beginning end Return iterator to end rbegin

STL Deque Iterators: begin Return iterator to beginning end Return iterator to end rbegin Return reverse iterator to reverse beginning rend Return reverse iterator to reverse end Capacity: size Return size max_size Return maximum size resize Change size empty is empty? Element access: operator[] Access element at Access element front Access first element back Access last element Modifiers: assign Assign container content void assign ( Input. Iterator first, Input. Iterator last ); void assign ( size_type n, const T& u ); push_back Add element at the end push_front Insert element at begin pop_back Delete last element pop_front Delete first element insert Insert elements (iterator position) erase Erase elements swap Swap content clear Clear content 10

STL Deque Constructors deque<int> first; deque<int> second (4, 100); deque<int> third (second. begin(), second.

STL Deque Constructors deque<int> first; deque<int> second (4, 100); deque<int> third (second. begin(), second. end()); deque<int> fourth (third); int myints[] = {16, 2, 77, 29}; deque<int> fifth (myints, myints + sizeof(myints) / sizeof(int) ); 11

STL Deque Comparable to vector methods: void clear ( ); iterator erase ( iterator

STL Deque Comparable to vector methods: void clear ( ); iterator erase ( iterator position ); iterator erase ( iterator first, iterator last ); reference front ( ); iterator insert ( iterator position, const T& x ); void insert ( iterator position, size_type n, const T& x ); void insert ( iterator position, Input. Iterator first, Input. Iterator last ); void pop_back ( ); void pop_front ( ); void push_back ( const T& x ); void push_front ( const T& x ); void swap ( deque<T, Allocator>& dqe ); 12

STL Deque Access methods: const_reference at ( size_type n ) const; reference at (

STL Deque Access methods: const_reference at ( size_type n ) const; reference at ( size_type n ); for (i=0; i<mydeque. size(); i++) mydeque. at(i)=i; cout << "mydeque contains: "; for (i=0; i<mydeque. size(); i++) cout << " " << mydeque. at(i); 13

STL Deque Implementation Design criteria: 1. 2. 3. 4. Elements accessed by position Elements

STL Deque Implementation Design criteria: 1. 2. 3. 4. Elements accessed by position Elements efficiently added/removed from either end Linear time add/removed from middle No guarantee to contiguous elements What sort of designs would work? What is the better design and why? 14

Deque Implementation • two common ways to implement: – a modified dynamic array –

Deque Implementation • two common ways to implement: – a modified dynamic array – an array of arrays a modified dynamic array • can grow from both ends • all the properties of a dynamic array: – such as constant time random access – good locality of reference – inefficient insertion/removal in the middle – constant time insertion/removal at both ends, instead of just one end. 15

Deque Implementation Common implementations for dynamic array: • Using a circular buffer, and only

Deque Implementation Common implementations for dynamic array: • Using a circular buffer, and only resizing when the buffer becomes completely full. (back) OUT BACK IN BACK OUT FRONT (front) IN FRONT 16

Deque Implementation Common implementations for dynamic array: • Allocating deque contents from the center

Deque Implementation Common implementations for dynamic array: • Allocating deque contents from the center of the underlying array, and resizing the underlying array when either end is reached. This approach may require more frequent resizings and waste more space, particularly when elements are only inserted at one end. Back Front 17

Deque Implementation • A dynamic array of fixed arrays (blocks) • Deque class keeps

Deque Implementation • A dynamic array of fixed arrays (blocks) • Deque class keeps all this information and provides a uniform access to the elements. 18

STL Stack Implementation Design criteria: 1. 2. Efficient access of top element Elements efficiently

STL Stack Implementation Design criteria: 1. 2. Efficient access of top element Elements efficiently added/removed from one end What sort of design would work? What is the better design and why? 19

Stack implementation possibilities Selecting a Storage Structure for a Stack • Model with an

Stack implementation possibilities Selecting a Storage Structure for a Stack • Model with an array – Let position 0 be top of stack • Problem … consider pushing and popping – Requires much shifting NOT EFFICIENT 20

Selecting Storage Structure • A better approach is to let position 0 be the

Selecting Storage Structure • A better approach is to let position 0 be the bottom of the stack • Thus our design will include – An array to hold the stack elements – An integer to indicate the top of the stack 21

Implementing Operations • Constructor (static array) – Compiler will handle allocation of memory •

Implementing Operations • Constructor (static array) – Compiler will handle allocation of memory • Empty – Check if value of my. Top == -1 • Push (if my. Array not full) – Increment my. Top by 1 – Store value in my. Array[my. Top] • Top – If stack not empty, return my. Array[my. Top] • Pop – If array not empty, decrement my. Top 22

Dynamic Array to Store Stack Elements • Issues regarding static arrays for stacks: –

Dynamic Array to Store Stack Elements • Issues regarding static arrays for stacks: – Can run out of space if stack set too small – Can waste space if stack set too large • As before, we demonstrate a dynamic array implementation to solve the problems • What additional data members required? Stack_ptr - pointer to dynamic stack Capacity - capacity of stack 23

Dynamic Array to Store Stack Elements • Constructor stack A(5) must: – Check that

Dynamic Array to Store Stack Elements • Constructor stack A(5) must: – Check that specified num. Elements > 0 – Set capacity to num. Elements – Allocate an array pointed to by my. Array with capacity = my. Capacity – Set my. Top to -1 if allocation goes OK What additional methods are required for this dynamic array approach? 24

Dynamic Array to Store Stack Elements • Class Destructor needed – Avoids memory leak

Dynamic Array to Store Stack Elements • Class Destructor needed – Avoids memory leak – Deallocates array allocated by constructor 25

Dynamic Array to Store Stack Elements • Copy Constructor needed for – Initializations –

Dynamic Array to Store Stack Elements • Copy Constructor needed for – Initializations – Passing value parameter – Returning a function value – Creating a temporary storage value • Provides for deep copy 26

Dynamic Array to Store Stack Elements • Assignment operator – Again, deep copy needed

Dynamic Array to Store Stack Elements • Assignment operator – Again, deep copy needed – copies member-by-member, not just address 27

Further Considerations • What if dynamic array initially allocated for stack is too small?

Further Considerations • What if dynamic array initially allocated for stack is too small? – Terminate execution? – Replace with larger array! WE’VE SEEN THIS BEFORE! • Stack Creating built a onlarger top ofarray Vector (dynamic array) – Allocate larger array – Use loop to copy elements into new array – Delete old array – Point my. Array variable at this new array 28

Further Considerations • Another weakness – in the previous scenario the type must be

Further Considerations • Another weakness – in the previous scenario the type must be set with typedef mechanism • This means we can only have one type of Class Template stack. Solution: in a program – Would require completely different stack declarations and implementations 29

Linked Stacks built on top of lists • Another alternative to allowing stacks to

Linked Stacks built on top of lists • Another alternative to allowing stacks to grow as needed • Linked list stack needs only one data member – Pointer my. Top – Nodes allocated (but not directly part of stack class) 30

Implementing Linked Stack Operations • Constructor – Simply assign null pointer to my. Top

Implementing Linked Stack Operations • Constructor – Simply assign null pointer to my. Top • Empty – Check for my. Top == null • Push – Insertion at beginning of list • Top – Return data to which my. Top points 31

Implementing Linked Stack Operations • Pop – Delete first node in the linked list

Implementing Linked Stack Operations • Pop – Delete first node in the linked list ptr = my. Top; my. Top = my. Top->next; delete ptr; • Output – Traverse the list for (ptr = my. Top; ptr != 0; ptr = ptr->next) out << ptr->data << endl; 32

Implementing Linked Stack Operations • Destructor – Must traverse list and deallocate nodes –

Implementing Linked Stack Operations • Destructor – Must traverse list and deallocate nodes – Note need to keep track of ptr->next before calling delete ptr; • Copy Constructor – Traverse linked list, copying each into new node – Attach new node to copy 33

Implementing Linked Stack Operations • Assignment operator – Similar to copy constructor – Must

Implementing Linked Stack Operations • Assignment operator – Similar to copy constructor – Must first rule out self assignment – Must destroy list in stack being assigned a new value 34

STL Stack Implementation • implemented as container adaptors, which are classes that use an

STL Stack Implementation • implemented as container adaptors, which are classes that use an encapsulated object of a specific container class as its underlying container The underlying structure of the stack the standard container class templates vector, deque or list can be used. By default - deque is used. template < class T, class Container = deque<T> > class stack; stack<int, vector<int> > binary; stack<int> binary; (deque is used) 35

STL Stack Implementation Constructors for Stack deque<int> mydeque (3, 100); // deque with 3

STL Stack Implementation Constructors for Stack deque<int> mydeque (3, 100); // deque with 3 elements vector<int> myvector (2, 200); // vector with 2 elements stack<int> first; // empty stack<int> second (mydeque); // stack initialized to copy of deque stack<int, vector<int> > third; // empty stack using vector stack<int, vector<int> > fourth (myvector); 36

Application of Stacks Consider events when a function begins execution • Activation record (or

Application of Stacks Consider events when a function begins execution • Activation record (or stack frame) is created • Stores the current environment for that function. • Contents: 37

Run-time Stack (call stack) • Functions may call other functions – interrupt their own

Run-time Stack (call stack) • Functions may call other functions – interrupt their own execution • Must store the activation records to be recovered – system then reset when first function resumes execution • This algorithm must have LIFO behavior • Structure used is the run-time stack 38

Use of Run-time Stack When a function is called … • Copy of activation

Use of Run-time Stack When a function is called … • Copy of activation record pushed onto runtime stack • Arguments copied into parameter spaces • Control transferred to starting address of body of function 39

Use of Run-time Stack When function terminates • Run-time stack popped – Removes activation

Use of Run-time Stack When function terminates • Run-time stack popped – Removes activation record of terminated function – exposes activation record of previously executing function • Activation record used to restore environment of interrupted function • Interrupted function resumes execution 40

Call Stack for Motorola 68000 processor int Calling. Function(int x) { int y; Called.

Call Stack for Motorola 68000 processor int Calling. Function(int x) { int y; Called. Function(1, 2); return (5); } void Called. Function(int param 1, int param 2) { int local 1, local 2; local 1 = param 2; } 41

Application of Stacks Consider the arithmetic statement in the assignment statement: x=a*b+c Compiler must

Application of Stacks Consider the arithmetic statement in the assignment statement: x=a*b+c Compiler must generate machine instructions 1. LOAD a Note: this is "infix" notation The operators are between 2. MULT b the operands 3. ADD c 4. STORE x 42

RPN or Postfix Notation • Most compilers convert an expression in infix Conversion from

RPN or Postfix Notation • Most compilers convert an expression in infix Conversion from infix to postfix: notation to postfix Rule 1: Scan the infix expression from left to right. – the operators areoperand writtenasafter operands Immediately record an soonthe as you identify it the expression • in. So a * b + c becomes a b * c + Rule 2: Record an operator as soon as you identify its • operands Advantage: – expressions can be written without parentheses Infix (a+b)*c (a*b+c)/d+e Postfix ab+c* ab*c+d/e+ 43

Postfix and Prefix Examples INFIX A+B A*B+C A * (B + C) A -

Postfix and Prefix Examples INFIX A+B A*B+C A * (B + C) A - (B - (C - D)) A-B-C-D RPN (POSTFIX) A A A B + B * C + B C + * B C D--B-C-D- PREFIX + A B + * A B C * A + B C -A-B-C D ---A B C D Prefix : Operators come before the operands 44

Evaluating RPN Expressions "By hand" (Underlining technique): 1. Scan the expression from left to

Evaluating RPN Expressions "By hand" (Underlining technique): 1. Scan the expression from left to right to find an operator. 2. Locate ("underline") the last two preceding operands and combine them using this operator. 3. Repeat until the end of the expression is reached. Example: 2 2 2 3 3 7 7 4 + 5 6 5 6 - -1 - * - - * * * 2 8 * 16 45

Evaluating RPN Expressions By using a stack algorithm 1. Initialize an empty stack 2.

Evaluating RPN Expressions By using a stack algorithm 1. Initialize an empty stack 2. Repeat the following until the end of the expression is encountered a) Get the next token (const, var, operator) in the expression b) Operand – push onto stack Note: if only 1 value on stack, this is an invalid Operator – do the following i. Pop 2 values from stack ii. Apply operator to the two values iii. Push resulting value back onto stack RPN expression 3. When end of expression encountered, value of expression is the (only) number left in stack 46

Evaluation of Postfix • Note the changing status of the stack 47

Evaluation of Postfix • Note the changing status of the stack 47

Converting Infix to RPN By hand: Represent infix expression as an expression tree: A

Converting Infix to RPN By hand: Represent infix expression as an expression tree: A * B + C A * (B + C) * + * A ((A + B) * C) / (D - E) / A C B B D x D y x - * + + C A C D E B y 48

/ Traverse the tree in Left-Right-Parent order (postorder) to get RPN: - * AB

/ Traverse the tree in Left-Right-Parent order (postorder) to get RPN: - * AB + C*DE-/ + Traverse tree in Parent-Left-Right order (preorder) to get prefix: A / B - * / * + A BC- D E + Traverse tree in Left-Parent-Right order (inorder) to get infix: — must insert ()'s E D C / A B + ( ((A + B) * C)/(D - E) ) A - * C E D B 49

Another RPN Conversion Method By hand: "Fully parenthesize-move-erase" method: 1. Fully parenthesize the expression.

Another RPN Conversion Method By hand: "Fully parenthesize-move-erase" method: 1. Fully parenthesize the expression. 2. Replace each right parenthesis by the corresponding operator. 3. Erase all left parentheses. Examples: A * B + C ((A * B) + C) ((A B * C + A * (B + C) (A * (B + C) ) (A (B C + * A B C + * 50

Stack Algorithm convert from infix to postfix 1. Initialize an empty stack of operators

Stack Algorithm convert from infix to postfix 1. Initialize an empty stack of operators 2. While no error && !end of expression a) Get next input "token" from infix expression b) If token is … const, var, arith operator, left or right paren i. "(" : push onto stack ii. ")" : pop and display stack elements until "(" occurs, do not display it 51

Stack Algorithm Note: Left parenthesis in stack has lower priority than operators iii. operator

Stack Algorithm Note: Left parenthesis in stack has lower priority than operators iii. operator if operator has higher priority than top of stack push token onto stack else pop and display top of stack repeat comparison of token with top of stack iv. operand display it 3. When end of infix reached, pop and display stack items until empty 52