我如何使用两个堆栈(LIFO),以便它可以像队列(FIFO)一样工作?

时间:2011-02-05 09:15:42

标签: c stack queue

我有两个堆栈(跟随LIFO)。我想知道我是否可以编写一个C程序来使用这两个堆栈就像一个队列(FIFO)。

3 个答案:

答案 0 :(得分:4)

一个堆栈用于将新元素插入队列。另一个堆栈用于删除元素。当输出堆栈为空时,输入堆栈将反转并成为新的输出堆栈。

在伪C中:

typedef struct { stack in, stack out } queue.

void insert(queue *q, void *data) {
  push(q->in, data);
}

void* remove(queue *q) {
  if (empty(q->out)) {
    while (!empty(q->in)) { // q->out = reversed q->in
      push(q->out, pop(q->in)); 
    }
  }
  return pop(q->out);  // assumes that it returns NULL if q->out is empty
}

这与常规队列的渐近相同,但每个元素都被触摸了好几次。既然你在C中工作,为什么不使用常规的环形缓冲区?

编辑:这确实是Okasaki的功能排队工作方式,@ bdonlan的答案提到了。

答案 1 :(得分:2)

其中一种技术描述如下:

  

Chris Okasaki(1995)。简单而有效的纯功能队列和deques。功能编程杂志,5,第583-592页

Fulltext is available in postscript format。这种技术是在函数式编程方面描述的,但没有根本原因可以解释为什么你也不能在C中实现它。

答案 2 :(得分:1)

(为什么不直接使用队列?)

基本上你使用一个堆栈B来反转另一个堆栈B中元素的顺序,方法是弹出A中的所有元素并将它们推入B.当你完成后,你将从B弹出的第一个对象是你推入原始A的第一个。

如果按此顺序将元素1, 2, 3, 4推送到A中,您将获得:

A: 1, 2, 3, 4 (top)

弹出一切并推进B:

B: 4, 3, 2, 1 (top)

如果你开始弹出B,你会得到顺序:

1, 2, 3, 4

复合操作是类似FIFO的结构。但是,它没有适当FIFO的灵活性,因为它只适用于通过。 可能在低端微控制器的代码中很有用,因为实现堆是一个问题,但你不应该在任何现代(即1980年后)的计算机上使用这样的堆栈。