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 with only one solution : each time we want the front element of the FIFO, copy the lifo into another lifo (excluding last element, which is the front), get the front element and remove it, then copy back the second LIFO into the first LIFO.
But this is of course horribly slow, it makes a simple loop like this :
for(!myfifo.empty()) {
myfifo.pop();
}
going O(n²) instead of O(n) on a standard implementation of the FIFO.
Of course, LIFO are not made to do FIFO and we won't certainly have the same complexity by using a "native" FIFO and a fake-FIFO based on a LIFO, but I think there is certainly a way of doing better than O(n²). Has anyone an idea about that ?
Thanks in advance.
To calculate FIFO (First-In, First Out) determine the cost of your oldest inventory and multiply that cost by the amount of inventory sold, whereas to calculate LIFO (Last-in, First-Out) determine the cost of your most recent inventory and multiply it by the amount of inventory sold.
FIFO (“First-In, First-Out”) assumes that the oldest products in a company's inventory have been sold first and goes by those production costs. The LIFO (“Last-In, First-Out”) method assumes that the most recent products in a company's inventory have been sold first and uses those costs instead.
FIFO (first in, first out) inventory management seeks to value inventory so the business is less likely to lose money when products expire or become obsolete. LIFO (last in, first out) inventory management is better for nonperishable goods and uses current prices to calculate the cost of goods sold.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With