【问题标题】:How to implement a dequeue using two stacks如何使用两个堆栈实现出队
【发布时间】:2012-09-02 11:15:26
【问题描述】:

出队 - 双端队列:可以从两端入队和出队。

如何使用 2 个堆栈定义出队的 ADT 操作。

实施还应考虑性能。

【问题讨论】:

  • @MitchWheat - 我找不到任何可以清楚地解释这个概念的好链接。如果你找到了,请分享一下。
  • @MitchWheat - 只能使用堆栈实现队列,不能使用两个堆栈进行出队。
  • @Harshdeep 这是作业吗?
  • @TylerCrompton - 不。我的一个朋友被问到这是在一次采访中,安德烈亚斯在答案中提到了我们能想到的唯一解决方案,但它在性能方面并不好。跨度>
  • 嗯,这是唯一的方法。真正应该使用链表(最好是单链表)来实现出队。这个问题可能更多的是试图确定你朋友的解决问题的能力。这就是为什么它也被称为头尾链表的原因。

标签: data-structures stack queue deque


【解决方案1】:

最简单的解决方案是使用一个堆栈作为队列的头部,一个作为尾部。 入队操作只是对相应堆栈的推送,而出队操作只是对相应堆栈的弹出操作。

但是,如果要从其中出列的堆栈为空,则必须从另一个堆栈中弹出每个元素并将其推回要从中出列的堆栈,然后将最后一个出列。这并不是很好的性能,所以这个实现的整体性能很大程度上取决于工作负载。如果您的工作负载是前/后入队和出队操作的数量平衡,那么这将非常非常快。但是,如果您的工作负载包含大量交替的头出列和尾出列,而队列很大,那么这显然是一个不好的方法。

希望对你有帮助

【讨论】:

  • 这也是我想出的解决方案,但正如您正确指出的那样,性能不好。是否可以对此实现进行任何修改以提高性能。
  • @Harshdeep 好吧,正如我所说,性能很大程度上取决于您的工作量。唯一会真正获得此实现弱点的工作负载是当您在大型队列上交替调用 frontDequeue 和 backDequeue 时。否则,这会很好。
  • 你的意思是frontEnqueue和backDequeue?
  • @Harshdeep 不,前入队和后出队都可以,因为元素只需移动一次“后出队”堆栈。但是,如果您从两端出队,则每次从另一端出队时,都必须将元素从一个堆栈移动到另一个堆栈。编辑:鉴于堆栈是空的...
  • 与 back-front-enqueue-dequeue 混淆了:P。感谢上述评论中的良好解释:)
【解决方案2】:

我就是这样做的, 真正重要的是,你要确保当你不断从一个弹出并且它变空时它开始从另一个弹出,(我们必须确保它从堆栈的末尾弹出)我们可以通过清空一个堆栈来做到这一点进入另一个。并继续在那里弹出。

公共类 NewDeque {

Stack<E> frontstack;
Stack<E> endstack;

public NewDeque() {

    frontstack = new Stack<>();
    endstack = new Stack<>();

}

void addFirst(E e) {

    frontstack.push(e);
}

E delFirst() {
    if (frontstack.isEmpty()) {
        while (!endstack.isEmpty()) {
            frontstack.push(endstack.pop());
        }
        return frontstack.pop();
    }
    return frontstack.pop();
}

void addLast(E e) {

    endstack.push(e);
}

E delLast() {
    if (endstack.isEmpty()) {
        while (!frontstack.isEmpty()) {
            endstack.push(frontstack.pop());
        }
        return endstack.pop();
    }
    return endstack.pop();
}

int size() {
    return frontstack.size() + endstack.size();
}

boolean isEmpty() {
    return (size() == 0) ? true : false;
}

E get(int i) {
    if (i < endstack.size()) {
        return endstack.get(endstack.size() - i - 1);
    } else {
        return frontstack.get(i - endstack.size());
    }

}

static void print(NewDeque<Integer> ds) {
    for (int i = 0; i < ds.size(); i++) {
        System.out.print(" " + ds.get(i) + " ");
    }
}

【讨论】:

    【解决方案3】:

    一个有趣的方法如下

    enqueue(q,  x)
      1) Push element x to stack1. This very simple, the problem is dequeue
    
    dequeue(q)
      1) If stacks1 and stack2 are empty then error  "UNDERFLOW"
      2) If stack2 is empty, then 
           while (stack1 is not empty) do
               push all element from satck1 to stack2.
            end while;
      3) Pop the element from stack2 and return it.
    

    【讨论】:

    • 这实现了一个队列,而不是一个出队。
    猜你喜欢
    • 2010-10-15
    • 2010-09-09
    • 2014-04-21
    • 2016-03-10
    • 2021-10-06
    • 2017-12-21
    • 2014-12-23
    • 1970-01-01
    • 2018-06-14
    相关资源
    最近更新 更多