Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement 3 stacks with one array?

Sometimes, I come across the following interview question: How to implement 3 stacks with one array ? Of course, any static allocation is not a solution.

like image 750
Michael Avatar asked Jan 22 '11 21:01

Michael


People also ask

Can multiple stacks can be implemented using a single array?

To implement two stacks in one array, there can be two methods. First is to divide the array in to two equal parts and then give one half two each stack. But this method wastes space. So a better way is to let the two stacks to push elements by comparing tops of each other, and not up to one half of the array.

Can we implement queue using 3 stacks?

This contradicts ASRT1 , therefore, it is not possible to simulate an O(1) queue with 3 stacks. I.e. At least 1 stack must be unbounded. For an element that stays in that stack, the number of elements above it must be bounded, or the dequeue operation to remove that element will be unbounded.

Can you have an array of stacks?

Sure. You can create arrays of any type, including classes and even other arrays!


2 Answers

Space (not time) efficient. You could:

1) Define two stacks beginning at the array endpoints and growing in opposite directions.

2) Define the third stack as starting in the middle and growing in any direction you want.

3) Redefine the Push op, so that when the operation is going to overwrite other stack, you shift the whole middle stack in the opposite direction before Pushing.

You need to store the stack top for the first two stacks, and the beginning and end of the third stack in some structure.

Edit

alt text

Above you may see an example. The shifting is done with an equal space partitioning policy, although other strategies could be chosen depending upon your problem heuristics.

Edit

Following @ruslik's suggestion, the middle stack could be implemented using an alternating sequence for subsequent pushes. The resulting stack structure will be something like:

| Elem 6 | Elem 4 | Elem 2 | Elem 0 | Elem 1 | Elem 3 | Elem 5 |

In this case, you'll need to store the number n of elements on the middle stack and use the function:

f[n_] := 1/4 ( (-1)^n (-1 + 2 n) + 1) + BS3   

to know the next array element to use for this stack.

Although probably this will lead to less shifting, the implementation is not homogeneous for the three stacks, and inhomogeneity (you know) leads to special cases, more bugs and difficulties to maintain code.

like image 147
Dr. belisarius Avatar answered Oct 11 '22 06:10

Dr. belisarius


As long as you try to arrange all items from one stack together at one "end" of the array, you're lacking space for the third stack.

However, you could "intersperse" the stack elements. Elements of the first stack are at indices i * 3, elements of the second stack are at indices i * 3 + 1, elements of the third stack are at indices i * 3 + 2 (where i is an integer).

+----+----+----+----+----+----+----+----+----+----+----+----+----+.. | A1 : B1 : C1 | A2 : B2 : C2 |    : B3 | C3 |    : B4 :    |    :   +----+----+----+----+----+----+----+----+----+----+----+----+----+..                   ^                        ^         ^                   A´s top                  C´s top   B´s top 

Of course, this scheme is going to waste space, especially when the stacks have unequal sizes. You could create arbitrarily complex schemes similar to the one described above, but without knowing any more constraints for the posed question, I'll stop here.

Update:

Due to the comments below, which do have a very good point, it should be added that interspersing is not necessary, and may even degrade performance when compared to a much simpler memory layout such as the following:

+----+----+----+----+----+----+----+----+----+----+----+----+----+.. | A1 : A2 :    :    :    | B1 : B2 : B3 : B4 :    | C1 : C2 : C3 :   +----+----+----+----+----+----+----+----+----+----+----+----+----+..        ^                                  ^                    ^        A´s top                            B´s top              C´s top 

i.e. giving each stack it's own contiguous block of memory. If the real question is indeed to how to make the best possible use of a fixed amount of memory, in order to not limit each stack more than necessary, then my answer isn't going to be very helpful.

In that case, I'd go with @belisarius' answer: One stack goes to the "bottom" end of the memory area, growing "upwards"; another stack goes to the "top" end of the memory area, growing "downwards", and one stack is in the middle that grows in any direction but is able to move when it gets too close to one of the other stacks.

like image 20
stakx - no longer contributing Avatar answered Oct 11 '22 06:10

stakx - no longer contributing