Stacks and Queues

3.1 Three in One: Describe how you could use a single array to implement three stacks.

  • Brain storm:

    • We can divide the array into 3 equal parts, and then define methods on each individual stack.

#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <utility>

using namespace std;

class stackArray3 {

public:
    stackArray3(int length) {

        if (length < 3) {
            cout << "size too small" << endl;
            return;
        }
        len = length;
        // create array
        stackArray = new int[length];

        // round down to ensure safe increments
        s1.first = ceil(length / 3) * 0;
        s2.first = ceil(length / 3) * 1;
        s3.first = ceil(length / 3) * 2;

        s1.second = s2.second = s3.second = 0;
    }

    void insert_top(int stackNum, int num) {
        switch (stackNum) {
        case 1:
            if (isFull(s1)) { cout << "stack is full" << endl; break; };
            stackArray[s1.first] = num;
            s1.first++; s1.second++;
            break;

        case 2:
            if (isFull(s2)) { cout << "stack is full" << endl; break; }
            stackArray[s2.first] = num;
            s2.first++; s2.second++;
            break;

        case 3:
            if (isFull(s3)) { cout << "stack is full" << endl; break; }
            stackArray[s3.first] = num;
            s3.first++; s3.second++;
            break;

        default: 
            cout << "invalid stack number" << endl;
            break;
        }
    }


    int top(int stackNum) {
        switch (stackNum) {
        case 1:
            if (isEmpty(s1)) { cout << "empty stack" << endl; return 0; }
            return stackArray[s1.first - 1];
            break;

        case 2:
            if (isEmpty(s2)) { cout << "empty stack" << endl; return 0; }
            return stackArray[s2.first - 1];
            break;

        case 3:
            if (isEmpty(s3)) { cout << "empty stack" << endl; return 0; }
            return stackArray[s3.first - 1];
            break;

        default:
            cout << "invalid stack number" << endl;
            break;
        }
    }

    int top_and_pop(int stackNum) {
        int ret;

        switch (stackNum) {
        case 1:
            if (isEmpty(s1)) { cout << "empty stack" << endl; return 0; }
            ret = stackArray[s1.first - 1];
            s1.first--; s1.second--;
            return ret;
            break;

        case 2:
            if (isEmpty(s2)) { cout << "empty stack" << endl; return 0; }
            return stackArray[s2.first - 1];
            ret = stackArray[s2.first - 1];
            s2.first--; s2.second--;
            return ret;
            break;

        case 3:
            if (isEmpty(s3)) { cout << "empty stack" << endl; return 0; }
            return stackArray[s3.first - 1];
            ret = stackArray[s2.first - 1];
            s2.first--; s2.second--;
            return ret;
            break;

        default:
            cout << "invalid stack number" << endl;
            break;
        }
    }

private:
    int *stackArray;
    int len;
    // index <-> count
    // current index in the stack <-> stack capacity
    std::pair<int, int> s1, s2, s3;

    bool isFull(pair<int, int> stackNum) {
        int num = ceil(len / 3);
        return stackNum.second >= ceil(len / 3);
    }

    bool isEmpty(pair<int, int> stackNum) {
        return stackNum.second == 0;
    }

};


int main()
{
    // even stack lengths -> cap = 2
    stackArray3 stackAr(6);

    stackAr.insert_top(1, 4);
    stackAr.insert_top(2, 5);
    stackAr.insert_top(3, 6);

    cout << stackAr.top(1) << endl;
    cout << stackAr.top(2) << endl;
    cout << stackAr.top(3) << endl;

    stackAr.insert_top(1, 7);
    stackAr.insert_top(2, 8);
    stackAr.insert_top(3, 9);

    cout << stackAr.top(1) << endl;
    cout << stackAr.top(2) << endl;
    cout << stackAr.top(3) << endl;

    // must be full
    stackAr.insert_top(1, 7);

    cout << endl << endl;


    // uneven stack lengths -> cap = 1
    stackArray3 stackAr2(4);

    stackAr2.insert_top(1, 4);
    stackAr2.insert_top(2, 5);
    stackAr2.insert_top(3, 6);

    cout << stackAr2.top(1) << endl;
    cout << stackAr2.top(2) << endl;
    cout << stackAr2.top(3) << endl;

    // must be full
    stackAr2.insert_top(1, 7);

}

3.2 Stack Min: How would you design a stack which, in addition to push and pop, has a function min which returns the minimum element? Push, pop and min should all operate in 0(1) time.

  • Brain storm:

    • Build a stack that contains stackNodes. Every time an a element is push onto the the stack, the minimum value will be assessed. The minimum will always be contained onto top of the stack and will always be the minimum of its substack. We will maintain order of the min values as we add or remove more elements into the stack.

3.3 Stack of Plates: Imagine a (literal) stack of plates. If the stack gets too high, it might topple. Therefore, in real life, we would likely start a new stack when the previous stack exceeds some threshold. Implement a data structure SetOfStacks that mimics this. SetOfStacks should be composed of several stacks and should create a new stack once the previous one exceeds capacity. SetOfStacks. push () and SetOfStacks. pop () should behave identically to a single stack (that is, pop ( ) should return the same values as it would if there were just a single stack).

FOLLOW UP Implement a function popAt (int index) which performs a pop operation on a specific sub-stack.

3.4 Queue via Stacks: Implement a MyQueue class which implements a queue using two stacks.

  • The idea is that stack.top() pushed back into another stack consequtively reverses the stack, so it can effectively become a queue.

3.5 Sort Stack: Write a program to sort a stack such that the smallest items are on the top. You can use an additional temporary stack, but you may not copy the elements into any other data structure (such as an array). The stack supports the following operations: push, pop, peek, and isEmpty.

  • The main idea is to hold a temporary variable for the current element on the top, and then continuing pushing off elements from the second stack until you find an appropriate spot for the temp var.

  • O(n^2) time, O(N) space

Last updated

Was this helpful?