# 1 Stacks Chapter 4. 2 Objectives You will be able to: Describe a stack as an ADT. Build a dynamic-array-based implementation of stacks. Build a linked-list.

## Presentation on theme: "1 Stacks Chapter 4. 2 Objectives You will be able to: Describe a stack as an ADT. Build a dynamic-array-based implementation of stacks. Build a linked-list."— Presentation transcript:

1 Stacks Chapter 4

2 Objectives You will be able to: Describe a stack as an ADT. Build a dynamic-array-based implementation of stacks. Build a linked-list implementation of stacks.

3 Stack A stack is a last-in-first-out (LIFO) data structure. Basic Operations: Add an item Referred to as pushing it onto the stack Remove an item Referred to as popping it from the stack

4 Stack as an ADT Definition: An ordered collection of data items. Can be accessed only at one end, the top Operations: Construct an empty stack Check if a stack is empty Push: Add an element to the top Pop:Remove the top element Top: Retrieve the top element

5 Example Consider a program to convert decimal numbers to binary Repeatedly Divide the decimal value by 2 Push the remainder onto a stack Continue until quotient is 0 Pop values off the stack and output

6 A Simple Stack Template Store stack elements in a dynamically allocated array. Member variable identifies top of stack. Throw an exception if client attempts to push an element when stack is full or pop an element when stack is empty.

stack.h #pragma once #include template class Stack { public:... private: T* data; // Dynamically allocated array int size; // Number of elements int top; // Index of element at top of stack // -1 when stack is empty };

stack.h #pragma once #include template class Stack { public: Stack(int capacity = 1000); ~Stack(); bool IsEmpty() const {return top == -1;}; bool IsFull() const {return top == size-1;}; // Add a value to the top of the stack. void Push(const T& value); // Remove and return value at top of stack. T Pop(); // Retrieve value at top of stack without removing it. T Top() const; // Display stack contents. void Display(std::ostream& out) const;

10 Constructor and Destructor template Stack ::Stack(int capacity): top(-1), size(capacity) { data = new T[capacity]; assert (data != 0); } template Stack ::~Stack() { delete[] data; }

11 Push() template void Stack ::Push(const T& value) { if (this->IsFull()) { throw "Stack overflow"; } data[++top] = value; }

12 Pop() template T Stack ::Pop() { if (this->IsEmpty()) { throw "Pop called for empty stack"; } return data[top--]; }

13 Top() template T Stack ::Top() const { if (this->IsEmpty()) { throw "Top of empty stack requested"; } return (data[top]); }

14 stack_test.cpp #include #include "Stack.h" #include using namespace std; const int STACK_CAPACITY = 10; int main() { Stack s(STACK_CAPACITY); assert (s.IsEmpty()); cout << "Newly created stack is empty\n"; printf ("Pushing 0 - %d \n", STACK_CAPACITY - 1); for (int i = 0; i < STACK_CAPACITY; ++i) { s.Push(i); } cout << "Initial stack:\n"; s.Display(cout);

15 stack_test.cpp assert(!s.IsEmpty()); cout << "Now the stack is not empty\n"; cout << "Adding one more element, which should cause overflow. " << endl; try { s.Push(1); cout << "ERROR\n"; // Should have thrown exception } catch (const char* msg) { cout << "Attempt to overfill stack threw exception as expected\n"; cout << "Message: " << msg << endl; } cout << "Stack should be unchanged\n" << endl; s.Display(cout);

16 stack_test.cpp cout << "Now poping elements off the stack\n"; while (!s.IsEmpty()) { int top = s.Top(); cout << "Stack top: " << top << endl; int next_item = s.Pop(); assert (next_item == top); } cout << "Stack is now empty\n"; cout << "Getting top of empty stack. This should fail\n"; try { int x = s.Top(); cout << "ERROR\n"; // Should have thrown exception } catch (const char* msg) { cout << "Attempt to get top of empty stack threw exception as expected\n"; cout << "Message: " << msg << endl; }

17 stack_test.cpp cout << "Doing one more pop. This should fail\n"; try { s.Pop(); cout << "ERROR\n"; // Should have thrown exception cin.get(); } catch (char* msg) { cout << "Attempt to pop empty stack threw exception as expected\n"; cout << "Message: " << msg << endl; }

18 stack_test.cpp cout << "Testing dynamic allocation\n"; Stack * s2 = new Stack (STACK_CAPACITY); assert(s2 != 0); cout << "Allocation was successful\n"; cout << "Testing delete\n"; delete(s2); s2 = 0; cout << "Delete was successful\n"; cout << "Test complete. Press Enter to exit." << endl; cin.get(); // Hold window open return 0; }

19 Program Running

20 Program Running

21 An Application: Decimal to Binary Conversion stack_demo.cpp /*-------------------------------------------------------------- This program uses a stack to convert the base-ten representation of a positive integer entered as input to base two, which is then output. ---------------------------------------------------------------------*/ #include #include "Stack.h" using namespace std; int main() { int number; // the number to be converted int remainder; // remainder when number is divided by 2 Stack remainders; // stack of remainders cout << "This program displays the binary representation of integers\n"; cout << "that you specify. Enter 0 to end program\n\n";

22 stack_demo.cpp while (true) { cout << "Enter positive integer to convert: "; cin >> number; if (number <= 0) { break; } while (number != 0) { remainder = number % 2; remainders.Push(remainder); number /= 2; } cout << "Base-two representation: "; while (!remainders.IsEmpty() ) { remainder = remainders.Pop(); cout << remainder; } cout << endl << endl; }

23 stack_demo.cpp cin.get(); // Hold window open cin.get(); return 0; }

24 Program in Action

25 Allocation Failure Let’s see if we can force an allocation failure and see what happens. Stack remainders(INT_MAX); // stack of remainders

26 stack_test.cpp #include #include "Stack.h" #include using namespace std; int main() { try { Stack* s = new Stack (INT_MAX); assert(s != 0); cout << "Allocation was successful\n"; } catch (bad_alloc& ba) { cout << "Caught Bad Allocation exception\n"; cout << ba.what() << endl; } cout << "Test complete. Press enter to exit.\n"; cin.get(); // Hold window open return 0; }