在网上看一些算法练习,我发现了一个有趣的算法:
如何使用LIFO实现FIFO?
我尝试了自己,但我最终只得到了一个解决方案:每次我们想要FIFO的前元素时,将lifo复制到另一个lifo(不包括最后一个元素获取正面元素并将其移除,然后将第二个LIFO复制回第一个LIFO。
但这当然非常慢,它就是这样一个简单的循环:
for(!myfifo.empty()) {
myfifo.pop();
}
在标准的FIFO实现上 O(n²)而不是 O(n)。
当然,LIFO不会做FIFO而我们通过使用基于LIFO的“原生”FIFO和假FIFO也不一定会有相同的复杂性,但我认为肯定有一种做法比O(n²)好。有没有人对此有所了解?
提前致谢。
答案 0 :(得分:13)
使用2个LIFO [堆栈],每个OP FIFO [队列]可以获得amortized time complexity个O(1)
。
假设您有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
示例:强>
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|
|-| |-|
要获得真实的O(1)
[未摊销],它要复杂得多,需要更多堆叠,请查看this post
编辑:复杂性分析:
insert()
都是trivaially O(1)
[只是推到stack1
] push()
次,pop()
最多两次,一次来自stack1
,另一次来自stack2
。由于没有其他操作,对于n
元素,我们最多只有2n
push()
和2n
pop()
s,这最多给了我们4n * O(1)
复杂度[因为pop()
和push()
都是O(1)
],O(n)
- 我们得到的摊销时间为:O(1) * 4n / n = O(1)
答案 1 :(得分:1)
LIFO和FIFO都可以用数组实现,它们之间的唯一区别在于 tail 和 head 指针的工作方式。假设你从LIFO开始,你可以添加两个额外的指针来反映FIFO的尾部和头部,然后使用FIFO指针添加方法添加,删除等等。
输出类型与专用FIFO或LIFO类型一样快,但它同时支持两者。您需要使用独特的类型成员,例如AddToStack / AddToQueue,RemoveFromStack / RemoveFromQueue等。