600 likes | 715 Views
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.
E N D
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. • A stack is a LIFO list.
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; virtualvoid pop() = 0; virtual void push(const T& theElement) = 0; };
Derive From A Linear List Class • arrayList • chain
a b c d e 0 1 2 3 4 5 6 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) orget(size() - 1) • O(1) time
a b c d e 0 1 2 3 4 5 6 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
a b c d e 0 1 2 3 4 5 6 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
firstNode NULL a b c d e 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
firstNode NULL a b c d e Derive From Chain • 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
firstNode null a b c d e Derive From Chain • 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
Derive From arrayList template<class T> class derivedArrayStack : private arrayList<T>, public stack<T> { public: // code for stack methods comes here };
Constructor derivedArrayStack(int initialCapacity = 10) : arrayList<T> (initialCapacity) {}
a b c d e 0 1 2 3 4 5 6 empty() And size() bool empty() const {return arrayList<T>::empty();} int size() const {return arrayList<T>::size();}
a b c d e 0 1 2 3 4 5 6 top() T& top() { if (arrayList<T>::empty()) throw stackEmpty(); return get(arrayList<T>::size() - 1); }
a b c d e 0 1 2 3 4 5 6 push(theElement) void push(const T& theElement) {insert(arrayList<T>::size(), theElement);}
a b c d e 0 1 2 3 4 5 6 pop() void pop() { if (arrayList<T>::empty()) throw stackEmpty(); erase(arrayList<T>::size() - 1); }
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.
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.
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.
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();}
Code From Scratch • Use a 1D array stack whose data type is T. • same as using array element in arrayList • Use an intvariable stackTop. • Stack elements are in stack[0:stackTop]. • Top element is in stack[stackTop]. • Bottom element is in stack[0]. • Stack is empty iff stackTop = -1. • Number of elements in stack is stackTop + 1.
Code From Scratch templateclass<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 };
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; }
top a b c d e 0 1 2 3 4 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; }
top a b c d e 0 1 2 3 4 pop() void pop() { if (stackTop == -1) throw stackEmpty(); stack[stackTop--].~T(); // destructor for T }
Linked Stack From Scratch • See text.
Performance 50,000,000 pop, push, and peek operations initial capacity Class 10 50,000,000 arrayStack 2.7s 1.5s derivedArrayStack 7.5s 6.3s STL 5.6s - derivedLinkedStack 41.0s 41.0s linkedStack 40.5s 40.5s
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.
The Abstract Class queue template <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; };
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.
a b c d e 0 1 2 3 4 5 6 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
a b c d e 0 1 2 3 4 5 6 Derive From arrayList • pop() => erase(0) • O(size) time • push(theElement) => insert(size(), theElement) • O(1) time
a b c d e 0 1 2 3 4 5 6 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
a b c d e 0 1 2 3 4 5 6 Derive From arrayList • pop() => erase(size() - 1) • O(1) time • push(theElement) => insert(0, theElement) • O(size) time
Derive From arrayList • to perform each opertion in O(1) time (excluding array doubling), we need a customized array representation.
lastNode firstNode NULL a b c d e front rear Derive From extendedChain • when front is left end of list and rear is right end • empty() => extendedChain::empty() • O(1) time • size() => extendedChain::size() • O(1) time
lastNode firstNode NULL a b c d e front rear Derive From ExtendedChain • front() => get (0) • O(1) time • back() => getLast() … new method
lastNode firstNode NULL a b c d e front rear Derive From ExtendedChain • push(theElement) => push_back(theElement) • O(1) time • pop() => erase(0) • O(1) time
lastNode firstNode NULL e d c b a rear front Derive From extendedChain • when front is right end of list and rear is left end • empty() => extendedChain::empty() • O(1) time • size() => extendedChain::size() • O(1) time
lastNode firstNode NULL a b c d e rear front Derive From extendedChain • front() => getLast() • O(1) time • back() => get(0) • O(1) time
lastNode firstNode NULL a b c d e rear front Derive From extendedChain • push(theElement) => insert(0, theElement) • O(1) time • pop() => erase(size() - 1) • O(size) time
Custom Linked Code • Develop a linked class for queue from scratch to get better preformance than obtainable by deriving from extendedChain.
queue[] [2] [3] [1] [4] [0] [5] Custom Array Queue • Use a 1D array queue. • Circular view of array.
[2] [3] A B C [1] [4] [0] [5] Custom Array Queue • Possible configuration with 3 elements.
[2] [3] C [1] [4] B A [0] [5] Custom Array Queue • Another possible configuration with 3 elements.
[2] [3] [2] [3] A B rear rear front front C C [1] [4] [1] [4] B A [0] [5] [0] [5] 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
[2] [3] A B rear front C [1] [4] [0] [5] Push An Element • Move rear one clockwise.
[2] [3] A B front C [1] [4] [0] [5] rear Push An Element • Move rear one clockwise. • Then put into queue[rear]. D
[2] [3] A B rear front C [1] [4] [0] [5] Pop An Element • Move front one clockwise.
[2] [3] front A B rear C [1] [4] [0] [5] Pop An Element • Move front one clockwise. • Then extract from queue[front].