# Implement Dynamic Multi Stack (K stacks) using only one Data Structure

• Last Updated : 24 Dec, 2021

In this article, we will see how to create a data structure that can handle multiple stacks with growable size. The data structure needs to handle three operations:

• push(x, stackNum) = pushes value x to the stack numbered stackNum
• pop(stackNum) = pop the top element from the stack numbered stackNum
• top(stackNum) = shows the topmost element of the stack stackNum.

### Example:

Suppose the given multi stack is [{1, 2}, {4, 6}, {9, 10}]

Input: push(3, 0), top(0)
push(7, 1), top(1)
pop(2), top(2)

Output: 3, 7, 9

Explanation: When 3 is pushed in stack 0, the stack becomes {1, 2, 3}. So the top element is 3.
When 7 is pushed in stack 1, the stack becomes {4, 6, 7}. So the top element is 7.
When topmost element is popped from stack 2, the stack becomes {9}. So the topmost element is 9

Approach: Follow the approach mentioned below to implement the idea.

• Store the size and the top index of every stack in arrays sizes[] and topIndex[].
• The sizes will be stored in a prefix sum array (using a prefix array sum will help us find the start/size of a stack in O(1) time)
• If the size of a stack reaches the maximum reserved capacity, expand the reserved size (multiply by 2)
• If the size of a stack gets down to a quarter of the reserved size shrink the reserved size (divide it by 2)
• Every time we need to expand/shrink a stack in the data structure, the indexes of other stacks might change so we need to take care of that. That is taken care by incrementing/decrementing value of sizes[] and topIndex[] arrays (we can do that in O(number of stacks) time).

Below is the implementation :

## C++

 `#include ``using` `namespace` `std;` `template` `<``typename` `T>` `// Class to implement multistack``class` `MultiStack {``    ``int` `numberOfStacks;``    ``vector values;``    ``vector<``int``> sizes, topIndex;` `public``:``    ``// Constructor to create k stacks``    ``// (by default 1)``    ``MultiStack(``int` `k = 1)``        ``: numberOfStacks(k)``    ``{``        ``// reserve 2 elements for each stack first``        ``values = vector(numberOfStacks << 1);` `        ``// For each stack store the index``        ``// of the element on the top``        ``// and the size (starting point)``        ``sizes = vector<``int``>(numberOfStacks);``        ``topIndex = vector<``int``>(numberOfStacks);` `        ``// Sizes is a prefix sum vector``        ``for` `(``int` `size = 2, i = 0; i < numberOfStacks;``             ``i++, size += 2)``            ``sizes[i] = size, topIndex[i] = size - 2;``    ``}` `    ``// Push a value in a stack``    ``void` `push(``int` `stackNum, T val)``    ``{` `        ``// Check if the stack is full,``        ``// if so Expand it``        ``if` `(isFull(stackNum))``            ``Expand(stackNum);` `        ``// Add the value to the top of the stack``        ``// and increment the top index``        ``values[topIndex[stackNum]++] = val;``    ``}` `    ``// Pop the top value and``    ``// return it form a stack``    ``T pop(``int` `stackNum)``    ``{` `        ``// If the stack is empty``        ``// throw an error``        ``if` `(empty(stackNum))``            ``throw``(``"Empty Stack!"``);` `        ``// Save the top value``        ``T val = values[topIndex[stackNum] - 1];` `        ``// Set top value to default data type``        ``values[--topIndex[stackNum]] = T();` `        ``// Shrink the reserved size if needed``        ``Shrink(stackNum);` `        ``// Return the pop-ed value``        ``return` `val;``    ``}` `    ``// Return the top value form a stack``    ``// Same as pop (but without removal)``    ``T top(``int` `stackNum)``    ``{``        ``if` `(empty(stackNum))``            ``throw``(``"Empty Stack!"``);``        ``return` `values[topIndex[stackNum] - 1];``    ``}` `    ``// Return the size of a stack``    ``// (the number of elements in the stack,``    ``// not the reserved size)``    ``int` `size(``int` `stackNum)``    ``{``        ``if` `(!stackNum)``            ``return` `topIndex;``        ``return` `topIndex[stackNum] - sizes[stackNum - 1];``    ``}` `    ``// Check if a stack is empty or not``    ``// (has no elements)``    ``bool` `empty(``int` `stackNum)``    ``{``        ``int` `offset;``        ``if` `(!stackNum)``            ``offset = 0;``        ``else``            ``offset = sizes[stackNum - 1];``        ``int` `index = topIndex[stackNum];``        ``return` `index == offset;``    ``}` `    ``// Helper function to check``    ``// if a stack size has reached``    ``// the reserved size of that stack``    ``bool` `isFull(``int` `stackNum)``    ``{``        ``int` `offset = sizes[stackNum];``        ``int` `index = topIndex[stackNum];``        ``return` `index >= offset;``    ``}` `    ``// Function to expand the reserved size``    ``// of a stack (multiply by 2)``    ``void` `Expand(``int` `stackNum)``    ``{` `        ``// Get the reserved_size of the stack()``        ``int` `reserved_size = size(stackNum);` `        ``// Update the prefix sums (sizes)``        ``// and the top index of the next stacks``        ``for` `(``int` `i = stackNum + 1; i < numberOfStacks; i++)``            ``sizes[i] += reserved_size,``                ``topIndex[i] += reserved_size;` `        ``// Update the size of the recent stack``        ``sizes[stackNum] += reserved_size;` `        ``// Double the size of the stack by``        ``// inserting 'reserved_size' elements``        ``values.insert(values.begin() + topIndex[stackNum],``                      ``reserved_size, T());``    ``}` `    ``// Function to shrink the reserved size``    ``// of a stack (divide by2)``    ``void` `Shrink(``int` `stackNum)``    ``{` `        ``// Get the reserved size and the current size``        ``int` `reserved_size, current_size;``        ``if` `(!stackNum)``            ``reserved_size = sizes,``            ``current_size = topIndex;``        ``else``            ``reserved_size``                ``= sizes[stackNum] - sizes[stackNum - 1],``                ``current_size``                ``= topIndex[stackNum] - sizes[stackNum - 1];` `        ``// Shrink only if the size is``        ``// lower than a quarter of the``        ``// reserved size and avoid shrinking``        ``// if the reserved size is 2``        ``if` `(current_size * 4 > reserved_size``            ``|| reserved_size == 2)``            ``return``;` `        ``// Divide the size by 2 and update``        ``// the prefix sums (sizes) and``        ``// the top index of the next stacks``        ``int` `dif = reserved_size / 2;``        ``for` `(``int` `i = stackNum + 1; i < numberOfStacks; i++)``            ``sizes[i] -= dif, topIndex[i] -= dif;``        ``sizes[stackNum] -= dif;` `        ``// Erase half of the reserved size``        ``values.erase(values.begin() + topIndex[stackNum],``                     ``values.begin() + topIndex[stackNum]``                         ``+ dif);``    ``}``};` `// Driver code``int` `main()``{``    ``// create 3 stacks``    ``MultiStack<``int``> MStack(3);` `    ``// push elements in stack 0:``    ``MStack.push(0, 21);``    ``MStack.push(0, 13);``    ``MStack.push(0, 14);` `    ``// Push one element in stack 1:``    ``MStack.push(1, 15);` `    ``// Push two elements in stack 2:``    ``MStack.push(2, 1);``    ``MStack.push(2, 2);``    ``MStack.push(2, 3);` `    ``// Print the top elements of the stacks``    ``cout << MStack.top(0) << ``'\n'``;``    ``cout << MStack.top(1) << ``'\n'``;``    ``cout << MStack.top(2) << ``'\n'``;` `    ``return` `0;``}`
Output
```14
15
3```

Time complexities:

• O(1) for top() function.
• Amortized O(1) for push() and pop() functions.

Auxiliary Space: O(N) where N is the number of stacks

My Personal Notes arrow_drop_up