【问题标题】:How can i use two stacks(LIFO) so that it can work like a queue(FIFO)?我如何使用两个堆栈(LIFO)以便它可以像队列(FIFO)一样工作?
【发布时间】:2011-06-21 19:41:03
【问题描述】:

我有两个堆栈(遵循 LIFO)。我想知道我是否可以编写一个 C 程序来使用这两个堆栈像队列(FIFO)一样工作。

【问题讨论】:

  • 使用队列不是更简单吗?
  • 我猜,因为 LIFO 反转了进来的元素,如果你使用两个 LIFO,你会反转它们两次。但如果 push 和 pop 不同步,这将不起作用。
  • @David Heffernan:有时堆栈是在硬件中实现的。

标签: c stack queue


【解决方案1】:

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

在伪 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 中工作,为什么不使用常规的环形缓冲区呢?

编辑:这确实是@bdonlan 的回答提到的冈崎功能队列的工作方式。

【讨论】:

    【解决方案2】:

    一种这样的技术描述在:

    克里斯冈崎 (1995)。简单高效的纯功能队列和双端队列。函数式编程杂志,5,第 583-592 页

    Fulltext is available in postscript format。这种技术是用函数式编程来描述的,但没有根本原因你不能用 C 来实现它。

    【讨论】:

      【解决方案3】:

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

      基本上,您使用一个堆栈 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 年后)计算机上使用这样的堆栈。

      【讨论】:

      • 就像有时堆栈会在硬件中实现,所以如果可以通过使用这些堆栈来获得队列功能,那么它将比软件对应物高效得多。
      • 能否详细说明However, it has none of the flexibility of a proper FIFO, since it only works in passes
      • 硬件实现必须比软件队列快 n^2。当然,对于小尺寸来说这可能是正确的,但一般情况下并非如此。
      • 如果您有两个堆栈可供使用,您可以摊销操作,使它们基本上变得与普通 FIFO 队列一样便宜,就像在@nominolo 的回答中一样。如果您有执行此操作的硬件辅助堆栈,我希望它比软件 FIFO 快一个数量级。
      猜你喜欢
      • 2020-10-08
      • 2010-09-09
      • 1970-01-01
      • 2014-05-26
      • 2017-03-23
      • 2014-04-21
      • 2011-11-29
      • 2010-10-15
      • 2020-08-30
      相关资源
      最近更新 更多