Top Banner
Stacks Linear list. One end is called top. Other end is called bottom. Additions to and removals from the top end only.
60

Stacks

Feb 22, 2016

Download

Documents

varen

Stacks. Linear list. One end is called top . Other end is called bottom . Additions to and removals from the top end only. . top. F. top. E. E. D. D. C. C. B. B. bottom. bottom. A. A. Stack Of Cups. Add a cup to the stack. Remove a cup from new stack. - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Stacks

Stacks

• Linear list.• One end is called top.• Other end is called bottom.• Additions to and removals from the top end

only.

Page 2: 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

Page 3: Stacks

The Abstract Class stack

template<class T>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;};

Page 4: Stacks

Derive From A Linear List Class

• arrayList• chain

Page 5: Stacks

Derive From arrayList

stack top is either left end or right end of linear list empty() => arrayList::empty()

• O(1) time size() => arrayList::size()

• O(1) time top() => get(0) or get(size() - 1)

• O(1) time

0 1 2 3 4 5 6

a b c d e

Page 6: Stacks

Derive From arrayList

• when top is left end of linear list push(theElement) => insert(0, theElement) O(size) time pop() => erase(0) O(size) time

0 1 2 3 4 5 6

a b c d e

Page 7: Stacks

Derive From arrayList

when top is right end of linear list• push(theElement) => insert(size(), theElement)• O(1) time• pop() => erase(size()-1)• O(1) time

use right end of list as top of stack

0 1 2 3 4 5 6

a b c d e

Page 8: Stacks

Derive From Chain

stack top is either left end or right end of linear list

empty() => chain::empty()• O(1) time

size() => chain::size()• O(1) time

a b c d e

NULL

firstNode

Page 9: Stacks

Derive From Chain

a b c d e

NULL

firstNode

– when top is left end of linear list top() => get(0) O(1) time push(theElement) => insert(0, theElement) O(1) time pop() => erase(0) O(1) time

Page 10: Stacks

Derive From Chain

a b c d enull

firstNode

– when top is right end of linear list• top() => get(size() - 1)• O(size) time• push(theElement) => insert(size(), theElement)• O(size) time• pop() => erase(size()-1)• O(size) time

– use left end of list as top of stack

Page 11: Stacks

Derive From arrayList

template<class T>class derivedArrayStack : private arrayList<T>, public stack<T>{ public: // code for stack methods comes here };

Page 12: Stacks

Constructor

derivedArrayStack(int initialCapacity = 10) : arrayList<T> (initialCapacity) {}

Page 13: Stacks

empty() And size()

bool empty() const{return arrayList<T>::empty();}

int size() const{return arrayList<T>::size();}

0 1 2 3 4 5 6

a b c d e

Page 14: Stacks

top()

T& top(){ if (arrayList<T>::empty()) throw stackEmpty(); return get(arrayList<T>::size() - 1);}

0 1 2 3 4 5 6

a b c d e

Page 15: Stacks

push(theElement)

void push(const T& theElement){insert(arrayList<T>::size(), theElement);}

0 1 2 3 4 5 6

a b c d e

Page 16: Stacks

pop()

void pop(){ if (arrayList<T>::empty()) throw stackEmpty(); erase(arrayList<T>::size() - 1);}

0 1 2 3 4 5 6

a b c d e

Page 17: Stacks

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<T> with private chain<T>• 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.

Page 18: Stacks

Demerits

• Unecessary work is done by the code. top() verifies that the stack is not empty before get

is invoked. The index check done by get is, therefore, not needed.

insert(size(), theElement) does an index check and a copy_backward. Neither is needed.

pop() verifies that the stack is not empty before erase is invoked. erase does an index check and a copy. Neither is needed.

So the derived code runs slower than necessary.

Page 19: Stacks

Evaluation

• Code developed from scratch will run faster but will take more time (cost) to develop.

• Tradeoff between software development cost and performance.

• Tradeoff between time to market and performance.

• Could develop easy code first and later refine it to improve performance.

Page 20: Stacks

A Faster pop()if (arrayList<T>::empty()) throw stackEmpty();erase(arrayList<T>::size() - 1);

vs.try {erase(arrayList<T>::size()-1);catch (illegalIndex{throw stackEmpty();}

Page 21: Stacks

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.

Page 22: Stacks

Code From Scratchtemplate class<T>class arrayStack : public stack<T>{ public: // public methods come here private: int stackTop; // current top of stack int arrayLength; // stack capacity T *stack; // element array};

Page 23: Stacks

Constructor

template<class T>arrayStack<T>::arrayStack(int initialCapacity){// Constructor. if (initialCapacity < 1) {// code to throw an exception comes here } arrayLength = initialCapacity; stack = new T[arrayLength]; stackTop = -1;}

Page 24: Stacks

push(…)

template<class T>void arrayStack<T>::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;}

0 1 2 3 4

a b c d e

top

Page 25: Stacks

pop()

void pop(){ if (stackTop == -1) throw stackEmpty(); stack[stackTop--].~T(); // destructor for T}

0 1 2 3 4

a b c d e

top

Page 26: Stacks

Linked Stack From Scratch

• See text.

Page 27: Stacks

Performance

50,000,000 pop, push, and peek operations initial capacityClass 10 50,000,000arrayStack 2.7s 1.5sderivedArrayStack 7.5s 6.3sSTL 5.6s -derivedLinkedStack 41.0s 41.0slinkedStack 40.5s 40.5s

Page 28: Stacks

Queues

• Linear list.• One end is called front.• Other end is called rear.• Additions are done at the rear only. • Removals are made from the front only.

Page 29: Stacks

The Abstract Class queuetemplate <class T>class queue { public: virtual ~queue() {} virtual bool empty() const = 0; virtual int size() const = 0; virtual T& front() = 0; virtual T& back() = 0; virtual void pop() = 0; virtual void push(const T& theElement) = 0;};

Page 30: Stacks

Revisit Of Stack Applications• Applications in which the stack cannot be

replaced with a queue. Parentheses matching. Towers of Hanoi. Switchbox routing. Method invocation and return. Try-catch-throw implementation.

• Application in which the stack may be replaced with a queue. Rat in a maze.

• Results in finding shortest path to exit.

Page 31: Stacks

Derive From arrayList

when front is left end of list and rear is right end• empty() => queue::empty()

– O(1) time• size() => queue::size(0)

– O(1) time• front() => get(0)

– O(1) time• back() => get(size() - 1)

– O(1) time

0 1 2 3 4 5 6

a b c d e

Page 32: Stacks

Derive From arrayList

• pop() => erase(0)– O(size) time

• push(theElement) => insert(size(), theElement)– O(1) time

0 1 2 3 4 5 6

a b c d e

Page 33: Stacks

Derive From arrayList

when front is right end of list and rear is left end• empty() => queue::empty()

– O(1) time• size() => queue::size(0)

– O(1) time• front() => get(size() - 1)

– O(1) time• back() => get(0)

– O(1) time

0 1 2 3 4 5 6

a b c d e

Page 34: Stacks

Derive From arrayList

• pop() => erase(size() - 1)– O(1) time

• push(theElement) => insert(0, theElement)– O(size) time

0 1 2 3 4 5 6

a b c d e

Page 35: Stacks

Derive From arrayList

to perform each opertion in O(1) time (excluding array doubling), we need a customized array representation.

Page 36: Stacks

Derive From extendedChain

a b c d e

NULL

firstNode lastNode

front rear when front is left end of list and rear is right end

• empty() => extendedChain::empty()– O(1) time

• size() => extendedChain::size()– O(1) time

Page 37: Stacks

Derive From ExtendedChain

a b c d e

NULL

firstNode lastNode

front rear

• front() => get (0)– O(1) time

• back() => getLast() … new method

Page 38: Stacks

Derive From ExtendedChain

a b c d e

NULL

firstNode lastNode

front rear

• push(theElement) => push_back(theElement)– O(1) time

• pop() => erase(0)– O(1) time

Page 39: Stacks

Derive From extendedChain

e d c b a

NULL

firstNode lastNode

rear front when front is right end of list and rear is left end

• empty() => extendedChain::empty()– O(1) time

• size() => extendedChain::size()– O(1) time

Page 40: Stacks

Derive From extendedChain

a b c d e

NULL

firstNode lastNode

rear front

• front() => getLast()– O(1) time

• back() => get(0)– O(1) time

Page 41: Stacks

Derive From extendedChain

a b c d e

NULL

firstNode lastNode

rear front

• push(theElement) => insert(0, theElement)– O(1) time

• pop() => erase(size() - 1)– O(size) time

Page 42: Stacks

Custom Linked Code

• Develop a linked class for queue from scratch to get better preformance than obtainable by deriving from extendedChain.

Page 43: Stacks

Custom Array Queue

• Use a 1D array queue.

queue[]

• Circular view of array.

[0]

[1]

[2] [3]

[4]

[5]

Page 44: Stacks

Custom Array Queue• Possible configuration with 3 elements.

[0]

[1]

[2] [3]

[4]

[5]

A B

C

Page 45: Stacks

Custom Array Queue• Another possible configuration with 3

elements.

[0]

[1]

[2] [3]

[4]

[5]AB

C

Page 46: Stacks

Custom Array Queue• Use integer variables theFront and theBack.

– theFront is one position counterclockwise from first element

– theBack gives position of last element– use front and rear in figures

[0]

[1]

[2] [3]

[4]

[5]

A B

Cfront rear

[0]

[1]

[2] [3]

[4]

[5]AB

Cfront

rear

Page 47: Stacks

Push An Element

[0]

[1]

[2] [3]

[4]

[5]

A B

Cfront rear

• Move rear one clockwise.

Page 48: Stacks

Push An Element• Move rear one clockwise.

[0]

[1]

[2] [3]

[4]

[5]

A B

Cfront

rear

• Then put into queue[rear].

D

Page 49: Stacks

Pop An Element

[0]

[1]

[2] [3]

[4]

[5]

A B

Cfront rear

• Move front one clockwise.

Page 50: Stacks

Pop An Element

[0]

[1]

[2] [3]

[4]

[5]

A B

C

frontrear

• Move front one clockwise.• Then extract from queue[front].

Page 51: Stacks

Moving rear Clockwise

[0]

[1]

[2] [3]

[4]

[5]

A B

Cfront rear

• rear++; if (rear = = arrayLength) rear = 0;

• rear = (rear + 1) % arrayLength;

Page 52: Stacks

Empty That Queue

[0]

[1]

[2] [3]

[4]

[5]AB

Cfront

rear

Page 53: Stacks

Empty That Queue

[0]

[1]

[2] [3]

[4]

[5]B

C

front

rear

Page 54: Stacks

Empty That Queue

[0]

[1]

[2] [3]

[4]

[5]

C

front

rear

Page 55: Stacks

Empty That Queue

• When a series of removes causes the queue to become empty, front = rear.

• When a queue is constructed, it is empty.• So initialize front = rear = 0.

[0]

[1]

[2] [3]

[4]

[5]front

rear

Page 56: Stacks

A Full Tank Please

[0]

[1]

[2] [3]

[4]

[5]AB

Cfront

rear

Page 57: Stacks

A Full Tank Please

[0]

[1]

[2] [3]

[4]

[5]AB

Cfront

rearD

Page 58: Stacks

A Full Tank Please

[0]

[1]

[2] [3]

[4]

[5]AB

Cfront

rearD E

Page 59: Stacks

A Full Tank Please

[0]

[1]

[2] [3]

[4]

[5]AB

Cfront

rear

D E

F

• When a series of adds causes the queue to become full, front = rear.

• So we cannot distinguish between a full queue and an empty queue!

Page 60: Stacks

Ouch!!!!!• Remedies.

Don’t let the queue get full.• When the addition of an element will cause the queue to be

full, increase array size.• This is what the text does.

Define a boolean variable lastOperationIsPush.• Following each push set this variable to true.• Following each pop set to false.• Queue is empty iff (front == rear) && !lastOperationIsPush• Queue is full iff (front == rear) && lastOperationIsPush