Stacks templateclass T class stack public virtual stack
Stacks template<class T> class stack { public: virtual ~stack() {} virtual bool empty() const = 0; virtual int size() const = 0; virtual T& top() = 0; virtual void push(const T& the. Element) = 0; };
Derive From A Linear List Class • array. List • chain
Derive From array. List a b c 0 1 2 d e 3 4 5 6 § stack top is either left end or right end of linear list § empty() => array. List: : empty() • O(1) time § size() => array. List: : size() • O(1) time § top() => get(0) or get(size() - 1) • O(1) time
Derive From array. List a b c 0 1 2 d e 3 4 5 6 • when top is left end of linear list § push(the. Element) => insert(0, the. Element) § O(size) time § pop() => erase(0) § O(size) time
Derive From array. List a b c 0 1 2 d e 3 4 5 6 § when top is right end of linear list • push(the. Element) => insert(size(), the. Element) • O(1) time • pop() => erase(size()-1) • O(1) time § use right end of list as top of stack
Derive From Chain first. Node NULL a b c d e § stack top is either left end or right end of linear list § empty() => chain: : empty() • O(1) time § size() => chain: : size() • O(1) time
Derive From Chain first. Node NULL a b c d e – when top is left end of linear list § top() => get(0) § O(1) time § push(the. Element) => insert(0, the. Element) § O(1) time § pop() => erase(0) § O(1) time
Derive From Chain first. Node null a b c d e – when top is right end of linear list • top() => get(size() - 1) • O(size) time • push(the. Element) => insert(size(), the. Element) • O(size) time • pop() => erase(size()-1) • O(size) time – use left end of list as top of stack
Derive From array. List template<class T> class derived. Array. Stack : private array. List<T>, public stack<T> { public: // code for stack methods comes here };
Constructor derived. Array. Stack(int initial. Capacity = 10) : array. List<T> (initial. Capacity) {}
empty() And size() a b c 0 1 2 d e 3 4 5 6 bool empty() const {return array. List<T>: : empty(); } int size() const {return array. List<T>: : size(); }
top() a b c 0 1 2 d e 3 4 5 6 T& top() { if (array. List<T>: : empty()) throw stack. Empty(); return get(array. List<T>: : size() - 1); }
push(the. Element) a b c 0 1 2 d e 3 4 5 6 void push(const T& the. Element) {insert(array. List<T>: : size(), the. Element); }
pop() a b c 0 1 2 d e 3 4 5 6 void pop() { if (array. List<T>: : empty()) throw stack. Empty(); erase(array. List<T>: : size() - 1); }
Evaluation • Merits of deriving from array. List § 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 array. List<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(), the. Element) 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 (array. List<T>: : empty()) throw stack. Empty(); erase(array. List<T>: : size() - 1); vs. try {erase(array. List<T>: : size()-1); catch (illegal. Index {throw stack. Empty(); }
Code From Scratch • Use a 1 D array stack whose data type is T. § same as using array element in array. List • Use an int variable stack. Top. § § § Stack elements are in stack[0: stack. Top]. Top element is in stack[stack. Top]. Bottom element is in stack[0]. Stack is empty iff stack. Top = -1. Number of elements in stack is stack. Top + 1.
Code From Scratch template class<T> class array. Stack : public stack<T> { public: // public methods come here private: int stack. Top; // current top of stack int array. Length; // stack capacity T *stack; // element array };
Constructor template<class T> array. Stack<T>: : array. Stack(int initial. Capacity) {// Constructor. if (initial. Capacity < 1) {// code to throw an exception comes here } array. Length = initial. Capacity; stack = new T[array. Length]; stack. Top = -1; }
push(…) a b c 0 1 2 d e 3 4 top template<class T> void array. Stack<T>: : push(const T& the. Element) {// Add the. Element to stack. if (stack. Top == array. Length - 1) {// code to double capacity coms here } // add at stack top stack[++stack. Top] = the. Element; }
pop() a b c 0 1 2 d e 3 4 top void pop() { if (stack. Top == -1) throw stack. Empty(); stack[stack. Top--]. ~T(); // destructor for T }
Linked Stack From Scratch • See text.
Performance 50, 000 pop, push, and peek operations initial capacity Class 10 50, 000 array. Stack 2. 7 s 1. 5 s derived. Array. Stack 7. 5 s 6. 3 s STL 5. 6 s derived. Linked. Stack 41. 0 s linked. Stack 40. 5 s
- Slides: 25