Introduction to the Stack ADTs: Stack: a data structure that holds a collection of elements of the same type. - The elements are accessed according to LIFO order: last in, first out - No random access to other elements Examples: - plates in a cafeteria - bangles... Applications : An "undo" mechanism in text editors; this operation is accomplished by keeping all text changes in a stack. o o o Undo/Redo stacks in Excel or Word. Compiler's syntax check for matching braces is implemented by using stack. Reverse a word. You push a given word to stack - letter by letter - and then pop letters from the stack. Back/Forward stacks on browsers. Support for recursion Fall 2018 Husain Gholoom Lecturer in Computer Science Page 1
Stack Operations - Operations: - push: add a value onto the top of the stack make sure it s not full first. - pop: remove (and return) the value from the top of the stack make sure it s not empty first. - peek() Return the element at the top of the stack without removing it, if the stack is not empty. - size() Return the number of elements in the stack. - isfull: true if the stack is currently full, i.e., has no more space to hold additional elements - isempty: true if the stack currently contains no elements - These operations should take constant time: O(1). - makeempty: removes all the elements ( This may take longer than constant time ) Stack Terms Stack overflow: - trying to push an item onto a full stack Stack underflow. - trying to pop an item from an empty stack Stack illustrated Fall 2018 Husain Gholoom Lecturer in Computer Science Page 2
Stack Application: Postfix notation Postfix notation is another way of writing arithmetic expressions. We normally use infix: the operator is between the operands In postfix notation, the operator is written after the two operands. infix: 2+5 postfix: 2 5 + Expressions are evaluated from left to right. Precedence rules and parentheses are never needed!! Simple Example : Assume that A = 4, B = 3, C = 2, D = 1 find the postfix notations then find the answer for the following infix : Infix Postfix notation Answer A + B A * B + C A * (B + C) A - (B - (C - D)) A - B - C - D 5 + ((1 + 2) 4) 3 Fall 2018 Husain Gholoom Lecturer in Computer Science Page 3
Postfix notation: using a stack Evaluation from left to right: push operands for operator: pop two values, perform operation Convert the following infix to postfix and evaluate using ( 4 + 5 ) * ( 7 2 ) Fall 2018 Husain Gholoom Lecturer in Computer Science Page 4
Evaluate Postfix Expression algorithm Using a stack: WHILE more input items exist get next item from input IF item is an operand stack.push(item) ELSE operand2 = stack.pop() operand1 = stack.pop() Compute result using item as operator stack.push(result) end WHILE result = stack.pop() Implementing a Stack Class Array implementation: - fixed size or use dynamic arrays - fixed arrays: size doesn t change - dynamic arrays: can resize as needed in pop Linked List - grow and shrink in size as needed Fall 2018 Husain Gholoom Lecturer in Computer Science Page 5
A static stack class class IntStack private: int *stackarray; // Pointer to the stack array int stacksize; // The stack size (will not change) int top; // Index to the top of the stack public: // Constructor IntStack(int); // Destructor ~IntStack(); // Stack operations void push(int); int pop(); bool isfull() const; bool isempty() const; void makeempty(); This implementation uses a dynamic stack, but it never resizes it once initialized. But it is capable of making a fixed size stack of any size. Fall 2018 Husain Gholoom Lecturer in Computer Science Page 6
A static stack class: functions //*********************************************** // Constructor * // This constructor creates an empty stack. The * // size parameter is the size of the stack. * //*********************************************** IntStack::IntStack(int size) stackarray = new int[size]; // dynamic alloc stacksize = size; // save for reference top = -1; // empty //*********************************************** // Destructor * //*********************************************** IntStack::~IntStack() delete [] stackarray; A static stack class: push //************************************************* // Member function push pushes the argument onto * // the stack. * //************************************************* void IntStack::push(int num) assert(!isfull()); top++; stackarray[top] = num; Fall 2018 Husain Gholoom Lecturer in Computer Science Page 7
A static stack class: pop //**************************************************** // Member function pop pops the value at the top * // of the stack off, and returns it. * //***************************************************** int IntStack::pop() assert(!isempty()); int num = stackarray[top]; top--; return num; A static stack class: functions //*************************************************** // Member function isfull returns true if the stack * // is full, or false otherwise. * //**************************************************** bool IntStack::isFull() const return (top == stacksize - 1); //**************************************************** // Member function isempty returns true if the stack * // is empty, or false otherwise. * //**************************************************** bool IntStack::isEmpty() const return (top == -1); Fall 2018 Husain Gholoom Lecturer in Computer Science Page 8
A static stack class: makeempty //**************************************************** // Member function makeempty makes the stack an * // empty stack. * //***************************************************** void IntStack::makeEmpty() top = -1; Fall 2018 Husain Gholoom Lecturer in Computer Science Page 9
A Stack Implementation using Arrays IntStack.h /* * stack.h * * Author: hag10 */ #ifndef STACK_H_ #define STACK_H_ class IntStack private: int *stackarray; // Pointer to the stack array int stacksize; // The stack size int top; // Indicates the top of the stack public: // Constructor IntStack(int); ; // Destructor ~IntStack(); // Stack operations void push(int); void pop(int &); bool isfull() const; bool isempty() const; #endif /* STACK_H_ */ Fall 2018 Husain Gholoom Lecturer in Computer Science Page 10
IntStack.cpp /* * stack.cpp * * Author: hag10 */ // Implementation file for the IntStach class #include <iostream> #include "IntStack.h" using namespace std; //*********************************************** // Constructor * // This constructor creates an empty stack. The * // size parameter is the size of the stack. * //*********************************************** IntStack::IntStack(int size) stackarray = new int[size]; stacksize = size; top = -1; Fall 2018 Husain Gholoom Lecturer in Computer Science Page 11
IntStack.cpp ( continued ) //*********************************************** // Destructor * //*********************************************** IntStack::~IntStack() delete [] stackarray; //************************************************* // Member function push pushes the argument onto * // the stack. * //************************************************* void IntStack::push(int num) if (isfull()) cout << "The stack is full.\n"; else top++; stackarray[top] = num; //**************************************************** // Member function pop pops the value at the top * // of the stack off, and copies it into the variable * // passed as an argument. * //**************************************************** void IntStack::pop(int &num) if (isempty()) cout << "The stack is empty.\n"; else num = stackarray[top]; top--; Fall 2018 Husain Gholoom Lecturer in Computer Science Page 12
IntStack.cpp ( continued ) //*************************************************** // Member function isfull returns true if the stack * // is full, or false otherwise. * //*************************************************** bool IntStack::isFull() const bool status; if (top == stacksize - 1) status = true; else status = false; return status; //**************************************************** // Member function isempty returns true if the stack * // is empty, or false otherwise. * //**************************************************** bool IntStack::isEmpty() const bool status; if (top == -1) status = true; else status = false; return status; Fall 2018 Husain Gholoom Lecturer in Computer Science Page 13
IntStackDriver.cpp /* * stackdriver.cpp * * Author: hag10 */ // This program demonstrates the IntStack class. #include <iostream> #include "Stack.h" using namespace std; int main() int catchvar; // To hold values popped off the stack // Define a stack object to hold 5 values. IntStack stack(5); // Push the values 5, 10, 15, 20, and 25 onto the stack. cout << "Pushing 5\n"; stack.push(5); cout << "Pushing 10\n"; stack.push(10); cout << "Pushing 15\n"; stack.push(15); cout << "Pushing 20\n"; stack.push(20); cout << "Pushing 25\n"; stack.push(25); cout << "Pushing 25\n"; stack.push(25); // Pop the values off the stack. cout << "Removing...\n"; stack.pop(catchvar); cout << catchvar << endl; stack.pop(catchvar); cout << catchvar << endl; stack.pop(catchvar); cout << catchvar << endl; stack.pop(catchvar); cout << catchvar << endl; stack.pop(catchvar); cout << catchvar << endl; return 0; Fall 2018 Husain Gholoom Lecturer in Computer Science Page 14
Sample Run Pushing 5 Pushing 10 Pushing 15 Pushing 20 Pushing 25 Removing... 25 20 15 10 5 What happens if you add the following statements cout << "Pushing 30\n"; stack.push(30); cout << "Pushing 35\n"; stack.push(35); cout << "Pushing 40\n"; stack.push(40); or stack.pop(catchvar); cout << catchvar << endl; stack.pop(catchvar); cout << catchvar << endl; stack.pop(catchvar); cout << catchvar << endl; Fall 2018 Husain Gholoom Lecturer in Computer Science Page 15
Introduction to the Queue Queue: a data structure that holds a collection of elements of the same type. - The elements are accessed according to FIFO order: first in, first out - No random access to other elements Examples: - One of the best examples of queue is print jobs sent to a printer. add a new print job to the queue (enqueue). The dequeue operation starts printing job starts. While printing, more jobs are added to the Q. When the printer finishes a current job, it pulls the next job from the Q and starts printing. Continuing this process until the Q is empty Other Examples: - People in line at a theatre box office - A line of people waiting for a bank teller - A line of cars at a toll both A Conceptual View of a Queue Fall 2018 Husain Gholoom Lecturer in Computer Science Page 16
Queue Operations Operations: o enqueue: add a value onto the rear of the queue (the end of the line) make sure it s not full first. o dequeue: remove a value from the front of the queue (the front of the line) Next! make sure it s not empty first. peek() Return the element of the queue without removing it, if the queue is not empty. size() Return the number of elements in the queue. o isfull: true if the queue is currently full, i.e., has no more space to hold additional elements o isempty: true if the queue currently contains no elements These operations should take constant time: O(1) o makeempty: removes all the elements This may take longer than constant time. Fall 2018 Husain Gholoom Lecturer in Computer Science Page 17
Queue illustrated int item; q.enqueue(2): q.enqueue(3); q.enqueue(5); item = q.dequeue(); //item is 2 item = q.dequeue(); //item is 3 q.enqueue(10); Note: front and rear are variables used by the implementation to carry out the operations Fall 2018 Husain Gholoom Lecturer in Computer Science Page 18
Queue implemented Just like stacks, queues can be implemented using arrays (fixed size, or resizing dynamic arrays) or linked lists (dynamic queues). The previous illustration assumed we were using an array to implement the queue When an item was dequeued, the items were NOT shifted up to fill the slot vacated by dequeued item. why not? Instead, both front and rear indices move in the array. Queue implemented : problem: end of the array When front and rear indices move in the array: Problem: rear hits end of array quickly Solution: wrap index around to front of array 7 9 6 front rear 3 7 9 6 rear front 3 4 7 9 6 rear front Fall 2018 Husain Gholoom Lecturer in Computer Science Page 19
Queue implemented : solution: wraparound To wrap the index back to the front of the array, use this code to increment rear during enqueue: if (rear == queuesize-1) rear = 0; else rear = rear+1; This code is equivalent to the following rear = (rear + 1) % queuesize; Do the same for advancing front index. Now, how do we know if the queue is empty or full? Queue implemented : problem: detecting full and empty queues When rear==front, is it full, or size==1? - Some implementations offset front or rear by 1. An easy solution: - Use a counter variable to keep track of the total number of items in the queue. enqueue: numitems++ dequeue: numitems-- isempty is true when numitems == 0 isfull is true when numitems == queuesize Queue implemented In the implementation that follows: the queue is a dynamically allocated array, whose size does not change front and rear are initialized to -1. If the queue is not empty: - rear is the index of the last item that was enqueued. - front+1 is the index of the next item to be dequeued. numitems: how many items are in the queue queuesize: the size of the array Fall 2018 Husain Gholoom Lecturer in Computer Science Page 20
A static queue class class IntQueue private: int *queuearray; // Points to the queue array int queuesize; // The queue size int front; // Subscript of the queue front int rear; // Subscript of the queue rear int numitems; // Number of items in the queue public: // Constructors/Destructor IntQueue(int); ~IntQueue(); ; // Queue operations void enqueue(int); int dequeue(); bool isempty() const; bool isfull() const; void makeempty(); Fall 2018 Husain Gholoom Lecturer in Computer Science Page 21
A static queue class: functions A static queue class: functions //****************************************************** // Creates an empty queue of a specified size. * //****************************************************** IntQueue::IntQueue(int s) queuearray = new int[s]; // dynamic alloc queuesize = s; // save for reference front = -1; // set up bookkeeping rear = -1; numitems = 0; //****************************************************** // Destructor * //****************************************************** IntQueue::~IntQueue() delete [] queuearray; Fall 2018 Husain Gholoom Lecturer in Computer Science Page 22
A static queue class: enqueue //****************************************************** // Enqueue inserts a value at the rear of the queue. * //****************************************************** Void IntQueue::enqueue(int num) assert(!isfull()); // Calculate the new rear position if (rear == queuesize-1) rear = 0; else rear = rear+1; // Insert new item queuearray[rear] = num; // Update item count numitems++; A static queue class: dequeue //****************************************************** // Dequeue removes the value at the front of the * // queue and copies t into num. * //****************************************************** int IntQueue::dequeue() assert(!isempty()); // Move front front = (front + 1) % queuesize; // Update item count numitems--; // Retrieve the front item return queuearray[front]; Fall 2018 Husain Gholoom Lecturer in Computer Science Page 23
A static queue class: functions //****************************************************** // isempty returns true if the queue is empty * //****************************************************** bool IntQueue::isEmpty() const return (numitems == 0); //****************************************************** // isfull returns true if the queue is full * //****************************************************** bool IntQueue::isFull() const return (numitems == queuesize); //***************************************************** // makeempty makes the stack empty * //***************************************************** void IntQueue::makeEmpty() front = - 1; rear = - 1; numitems = 0; Fall 2018 Husain Gholoom Lecturer in Computer Science Page 24
Array vs Linked List implementations Both are very fast (O(1)). Array may be faster (no dynamic allocation) Static arrays: - must anticipate maximum size - wasted space: entire array is allocated, even if using small portion Dynamic arrays (resize when full): - resizing takes time (copying all the elements) - resizing requires memory that is three times what is needed to store the elements at that time Linked List: - code is actually simpler than array with resizing, especially for queues. - space used by elements is always proportional to number of elements (only wasted space is for the pointers) Summary: - array implementation is probably better for small objects. - linked list is probably better for large objects if space is scarce or copying is expensive (resizing) Fall 2018 Husain Gholoom Lecturer in Computer Science Page 25
Queue Implementation using Arrays Queue.h /* * Queue.h * * Author: hag10 */ #ifndef QUEUE_H_ #define QUEUE_H_ class IntQueue private: int *queuearray; // Points to the queue array int queuesize; // The queue size int front; // Subscript of the queue front int rear; // Subscript of the queue rear int numitems; // Number of items in the queue public: // Constructor IntQueue(int); ; // Destructor ~IntQueue(); // Queue operations void enqueue(int); void dequeue(int &); bool isempty() ; bool isfull() ; #endif /* QUEUE_H_ */ Fall 2018 Husain Gholoom Lecturer in Computer Science Page 26
Queue.cpp /* * Queue.cpp * * Author: hag10 */ // Implementation file for the IntQueue class #include <iostream> #include "IntQueue.h" using namespace std; //*************************************************************** // This constructor creates an empty queue of a specified size. * //*************************************************************** IntQueue::IntQueue(int s) queuearray = new int[s]; queuesize = s; front = -1; rear = -1; numitems = 0; Fall 2018 Husain Gholoom Lecturer in Computer Science Page 27
IntQueue.cpp ( continued ) //*************************************************************** // Destructor * //*************************************************************** IntQueue::~IntQueue() delete [] queuearray; //*************************************************************** // Function enqueue inserts a value at the rear of the queue. * //*************************************************************** void IntQueue::enqueue(int num) if (isfull()) cout << "The queue is full.\n"; else // Calculate the new rear position if (rear == queuesize - 1) rear = 0; else rear = rear + 1; // Insert new item queuearray[rear] = num; // Update item count numitems++; cout<<num<<endl; //*************************************************************** // Function dequeue removes the value at the front of the queue * // and copies t into num. * //*************************************************************** void IntQueue::dequeue(int &num) if (isempty()) cout << "The queue is empty.\n"; else // Move front front = (front + 1) % queuesize; // Retrieve the front item num = queuearray[front]; // Update item count numitems--; Fall 2018 Husain Gholoom Lecturer in Computer Science Page 28
IntQueue.cpp ( continued ) //*************************************************************** // isempty returns true if the queue is empty, otherwise false. * //*************************************************************** bool IntQueue::isEmpty() bool status; if (numitems!= 0) status = false; else status = true; return status; //*************************************************************** // isfull returns true if the queue is full, otherwise false. * //*************************************************************** bool IntQueue::isFull() bool status; if (numitems < queuesize) status = false; else status = true; return status; Fall 2018 Husain Gholoom Lecturer in Computer Science Page 29
QueueDriver.cpp /* * QueueDriver.cpp * * Author: hag10 */ // This program demonstrates the IntQeue class #include <iostream> #include "Queue.h" using namespace std; int main() const int MAX_VALUES = 5; // Max number of values // Create an IntQueue to hold the values. IntQueue iqueue(max_values); // Enqueue a series of items. cout << "Enqueuing " << MAX_VALUES << " items...\n"; for (int x = 0; x < MAX_VALUES; x++) iqueue.enqueue(x); // Attempt to enqueue just one more item. cout << "\nnow attempting to enqueue again...\n"; iqueue.enqueue(max_values); // Deqeue and retrieve all items in the queue cout << "\ndequeuing : The values in the queue were:\n"; int value; while (!iqueue.isempty()) iqueue.dequeue(value); cout << value << endl; cout << endl << endl ; return 0; Fall 2018 Husain Gholoom Lecturer in Computer Science Page 30
Sample Run Enqueuing 5 items... 0 1 2 3 4 Now attempting to enqueue again... The queue is full. The values in the queue were: 0 1 2 3 4 Fall 2018 Husain Gholoom Lecturer in Computer Science Page 31
Stack in C++ STL Stacks are a type of container adaptors with LIFO(Last In First Out) type of working, where a new element is added at one end and (top) an element is removed from that end only. The functions associated with stack are: empty() Returns whether the stack is empty Time Complexity : O(1) size() Returns the size of the stack Time Complexity : O(1) top() Returns a reference to the top most element of the stack Time Complexity : O(1) push(g) Adds the element g at the top of the stack Time Complexity : O(1) pop() Deletes the top most element of the stack Time Complexity : O(1) Fall 2018 Husain Gholoom Lecturer in Computer Science Page 32
Queue in Standard Template Library (STL) Queues are a type of container adaptors which operate in a first in first out (FIFO) type of arrangement. Elements are inserted at the back (end) and are deleted from the front. The functions supported by queue are : empty() Returns whether the queue is empty size() Returns the size of the queue front() Returns a reference to the first element of the queue back() Returns a reference to the last element of the queue push(g) Adds the element g at the end of the queue pop() Deletes the first element of the queue Fall 2018 Husain Gholoom Lecturer in Computer Science Page 33
Example : // CPP program to demonstrate working of STL stack #include <iostream> #include <stack> using namespace std; void showstack(stack<int> s) while (!s.empty()) cout << '\t' << s.top(); s.pop(); cout << '\n'; int main() stack<int> s; s.push(10); s.push(30); s.push(20); s.push(5); s.push(1); cout << "The stack is : "; showstack(s); cout << "\ns.size() : " << s.size(); cout << "\ns.top() : " << s.top(); cout << "\ns.pop() : "; s.pop(); showstack(s); return 0; The stack is : 1 5 20 30 10 s.size() : 5 s.top() : 1 s.pop() : 5 20 30 10 Fall 2018 Husain Gholoom Lecturer in Computer Science Page 34
Example // Queue in Standard Template Library (STL) #include <iostream> #include <queue> using namespace std; void showq(queue<int> gq) queue<int> g = gq; while (!g.empty()) cout << '\t' << g.front(); g.pop(); cout << '\n'; int main() queue<int> gquiz; gquiz.push(10); gquiz.push(20); gquiz.push(30); cout << "The queue gquiz is : "; showq(gquiz); cout << "\ngquiz.size() : " << gquiz.size(); cout << "\ngquiz.front() : " << gquiz.front(); cout << "\ngquiz.back() : " << gquiz.back(); cout << "\ngquiz.pop() : "; gquiz.pop(); showq(gquiz); return 0; The queue gquiz is : 10 20 30 gquiz.size() : 3 gquiz.front() : 10 gquiz.back() : 30 gquiz.pop() : 20 30 Fall 2018 Husain Gholoom Lecturer in Computer Science Page 35