|
| 1 | +/** |
| 2 | + * @author [S-M-J-I](https://github.com/S-M-J-I) |
| 3 | + * @file |
| 4 | + * |
| 5 | + * Implementation of stack that retrieves the minimum element in constant time. |
| 6 | + * (https://www.baeldung.com/cs/stack-constant-time) |
| 7 | + * |
| 8 | + * @details |
| 9 | + * The MinStack data structure keeps track of the minimum element present in a |
| 10 | + * stack and retrieves them at O(1) time. |
| 11 | + */ |
| 12 | +#include <cassert> |
| 13 | +#include <iostream> |
| 14 | +#include <stack> |
| 15 | +#include <stdexcept> |
| 16 | + |
| 17 | +/** |
| 18 | + * @namespace |
| 19 | + * @brief data_structures |
| 20 | + */ |
| 21 | +namespace data_structures { |
| 22 | +/** |
| 23 | + * @brief Class representation of a the minimum stack |
| 24 | + */ |
| 25 | +class MinStack { |
| 26 | + private: |
| 27 | + /** |
| 28 | + * the mainStack keeps track of the elements in the stack |
| 29 | + * the minStack keeps track of the minimum elements present in the stack so |
| 30 | + * far |
| 31 | + */ |
| 32 | + std::stack<int> mainStack, minStack; |
| 33 | + |
| 34 | + public: |
| 35 | + /** |
| 36 | + * @brief Constructs a new MinStack object to initialize the mainStack and |
| 37 | + * the minStack |
| 38 | + */ |
| 39 | + MinStack() = default; |
| 40 | + |
| 41 | + /** |
| 42 | + * @brief Pushes the data in the stack. If the data is the minimum element |
| 43 | + * so far, then pushes it into the minStack to keep track of it. |
| 44 | + * @param data The element to be pushed to the stack |
| 45 | + */ |
| 46 | + void push(int data) { |
| 47 | + if (mainStack.empty()) { |
| 48 | + mainStack.push(data); |
| 49 | + minStack.push(data); |
| 50 | + return; |
| 51 | + } |
| 52 | + |
| 53 | + mainStack.push(data); |
| 54 | + if (data < minStack.top()) { |
| 55 | + minStack.push(data); |
| 56 | + } |
| 57 | + } |
| 58 | + |
| 59 | + /** |
| 60 | + * @brief Pops the data from the stack. If the data that is removed is the |
| 61 | + * minimum element, then remove it from the minStack as well. |
| 62 | + * @throws std::out_of_range if the stack is empty |
| 63 | + */ |
| 64 | + void pop() { |
| 65 | + if (mainStack.empty()) { |
| 66 | + throw std::out_of_range("Stack underflow"); |
| 67 | + } |
| 68 | + |
| 69 | + int top_ele = mainStack.top(); |
| 70 | + mainStack.pop(); |
| 71 | + if (top_ele == minStack.top()) { |
| 72 | + minStack.pop(); |
| 73 | + } |
| 74 | + } |
| 75 | + /** |
| 76 | + * @brief Gets the minimum element of the stack |
| 77 | + * @return The minimum element at the top of the minStack |
| 78 | + * @throws std::out_of_range if the minStack is empty |
| 79 | + */ |
| 80 | + int get_min() { |
| 81 | + if (minStack.empty()) { |
| 82 | + throw std::out_of_range("Stack underflow"); |
| 83 | + } |
| 84 | + return minStack.top(); |
| 85 | + } |
| 86 | +}; |
| 87 | +} // namespace data_structures |
| 88 | + |
| 89 | +/** |
| 90 | + * @brief test cases |
| 91 | + */ |
| 92 | +static void test() { |
| 93 | + data_structures::MinStack minStack; |
| 94 | + |
| 95 | + // Test pushing elements and checking the minimum element |
| 96 | + minStack.push(10); |
| 97 | + assert(minStack.get_min() == 10); |
| 98 | + |
| 99 | + minStack.push(20); |
| 100 | + assert(minStack.get_min() == 10); |
| 101 | + |
| 102 | + minStack.push(30); |
| 103 | + minStack.push(4); |
| 104 | + minStack.push(1); |
| 105 | + assert(minStack.get_min() == 1); |
| 106 | + |
| 107 | + // Test popping elements |
| 108 | + minStack.pop(); |
| 109 | + assert(minStack.get_min() == 4); |
| 110 | + minStack.pop(); |
| 111 | + assert(minStack.get_min() == 10); |
| 112 | + |
| 113 | + // Test minStack underflow |
| 114 | + try { |
| 115 | + minStack.pop(); |
| 116 | + minStack.pop(); |
| 117 | + minStack.pop(); |
| 118 | + minStack.pop(); |
| 119 | + } catch (const std::out_of_range& e) { |
| 120 | + assert(std::string(e.what()) == "Stack underflow"); |
| 121 | + } |
| 122 | + |
| 123 | + // Try to get the minimum from empty stack |
| 124 | + try { |
| 125 | + minStack.get_min(); |
| 126 | + } catch (const std::out_of_range& e) { |
| 127 | + assert(std::string(e.what()) == "Stack underflow"); |
| 128 | + } |
| 129 | +} |
| 130 | + |
| 131 | +/** |
| 132 | + * @brief Main function |
| 133 | + * @returns 0 on exit |
| 134 | + */ |
| 135 | +int main() { |
| 136 | + test(); // run self-test implementations |
| 137 | + std::cout << "All tests passed!" << std::endl; |
| 138 | + return 0; |
| 139 | +} |
0 commit comments