Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing FIFO using LIFO

Tags:

algorithm

fifo

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.

like image 255
Undo Avatar asked Mar 12 '12 08:03

Undo


People also ask

How do you calculate FIFO using LIFO?

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.

What is LIFO and FIFO with example?

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.

Why do you we use FIFO and LIFO methods?

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.


2 Answers

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:

  1. each insert() is trivaially O(1) [just pushing it to stack1]
  2. Note that each element is 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)
like image 173
amit Avatar answered Sep 20 '22 08:09

amit


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.

like image 29
oleksii Avatar answered Sep 19 '22 08:09

oleksii