Looking at some algorithm exercices on the net, I found an interesting one :
How would you implement a FIFO using a LIFO ?
I tried myself but I ended up wit
You can get amortized time complexity of O(1)
per OP FIFO [queue] using 2 LIFOs [stacks].
Assume you have stack1
, stack2
:
insert(e):
stack1.push(e)
take():
if (stack2.empty()):
while (stack1.empty() == false):
stack2.push(stack1.pop())
return stack2.pop() //assume stack2.pop() handles empty stack already
example:
push(1)
|1| | |
|-| |-|
push(2)
|2| | |
|1| | |
|-| |-|
pop()
push 2 to stack2 and pop it from stack1:
|1| |2|
|-| |-|
push 1 to stack2 and pop it from stack2:
| | |1|
| | |2|
|-| |-|
pop1 from stack2 and return it:
| | |2|
|-| |-|
To get real O(1)
[not amortized], it is much more complicated and requires more stacks, have a look at some of the answers in this post
EDIT: Complexity analysis:
insert()
is trivaially O(1)
[just pushing it to stack1
]push()
ed and pop()
ed at most twice, once from stack1
and once from stack2
. Since there is no more ops then these, for n
elements, we have at most 2n
push()
s and 2n
pop()
s, which gives us at most 4n * O(1)
complexity [since both pop()
and push()
are O(1)
], which is O(n)
- and we get amortized time of: O(1) * 4n / n = O(1)
Both LIFO and FIFO can be implemented with an array, the only difference between them is in the way tail and head pointers work. Given you start with LIFO, you can add two extra pointers that would reflect FIFO's tail and head, and then add methods to Add, Remove an so on using the FIFO pointers.
The output type would be as fast as a dedicated FIFO or LIFO type, however it would support both. You would need to use distinctive type members, like AddToStack/AddToQueue, RemoveFromStack/RemoveFromQueue etc.