使用队列实现堆栈 - 最佳复杂性

时间:2014-10-30 01:19:55

标签: algorithm stack queue time-complexity

我想知道是否有一种方法可以根据需要使用尽可能多的队列来实现堆栈,以便在O(1)中推送和弹出数据。 如果没有任何O(1)算法,那么最好的复杂度是什么?

3 个答案:

答案 0 :(得分:2)

如果允许队列中的递归定义队列,则可以使用以下方法进行O(1)推送/弹出:

代码:

STACK:
  QUEUE q

PUSH (S, x):
  QUEUE temp
  ENQUEUE(temp, x)
  ENQUEUE(temp, S.q)
  S.q = temp


POP (S):
  ANY x := DEQUEUE(S.q) # Error here if queue is empty
  QUEUE S.q := DEQUEUE(S.q)
  return x

结果是递归形成的堆栈。

如果[1,2]代表dequeue([1,2])将返回1的堆栈。然后,如果1然后3然后6被推入堆栈,数据结构将如下所示:

[6,[3,[1,[]]]]

答案 1 :(得分:1)

您可以使用线性时间PUSH和常量时间POP进行堆叠。

给定一个带有ENQUEUE和DEQUEUE函数的队列:

STACK:
  QUEUE q


PUSH (S, x):
  r := new QUEUE
  ENQUEUE(r, x)

  while S.q not empty:
    v := DEQUEUE(S.q)
    ENQUEUE(r, v)

  S.q := r


POP (S):
  RETURN DEQUEUE(S.q)

编辑:不需要临时队列r的替代解决方案:

STACK:
  QUEUE q


PUSH (S, x):
  ENQUEUE(S.q, x)

  n := SIZE(S.q) - 1

  repeat n times:
    v := DEQUEUE(S.q)
    ENQUEUE(S.q, v)


POP (S):
  RETURN DEQUEUE(S.q)

答案 2 :(得分:1)

这是一个带有O(1)推送和弹出函数的堆栈的C ++实现。

接口类似于std :: stack:

void push(const T& val);
void pop();
const T& top() const;
bool empty() const;

这是完整的代码。我无法想出一种避免凌乱的类型演员的方法。

#include <iostream>
#include <stack>
#include <queue>
#include <stdexcept>


#define ASSERT(x) \
  if (!(x)) { \
    std::cout << "Assertion failed at line " << __LINE__ << "\n"; \
  } \


template <typename T>
class Stack {
  public:
    Stack()
      : m_head(NULL), m_tail(NULL) {}

    void push(const T& val) {
      std::queue<void*>* tail = new std::queue<void*>();
      tail->push(reinterpret_cast<void*>(m_head));
      tail->push(reinterpret_cast<void*>(m_tail));

      m_head = new std::queue<T>();
      m_head->push(val);

      m_tail = tail;
    }

    void pop() {
      if (m_head) {
        delete m_head;

        m_head = reinterpret_cast<std::queue<T>*>(m_tail->front());
        m_tail->pop();

        std::queue<void*>* tail = reinterpret_cast<std::queue<void*>*>(m_tail->front());
        delete m_tail;
        m_tail = tail;
      }
    }

    const T& top() const {
      if (!m_head) {
        throw std::runtime_error("Error retrieving top element; stack empty");
      }

      return m_head->front();
    }

    bool empty() {
      return !m_head;
    }

  private:
    std::queue<T>* m_head;
    std::queue<void*>* m_tail;
};


int main() {
  Stack<int> s;

  s.pop();

  s.push(0);
  ASSERT(s.top() == 0);

  s.push(1);
  ASSERT(s.top() == 1);

  s.push(2);
  ASSERT(s.top() == 2);

  s.push(3);
  ASSERT(s.top() == 3);

  s.pop();
  ASSERT(s.top() == 2)

  s.push(4);
  ASSERT(s.top() == 4);

  s.push(5);
  ASSERT(s.top() == 5);

  s.push(6);
  ASSERT(s.top() == 6);

  s.pop();
  ASSERT(s.top() == 5)

  s.pop();
  ASSERT(s.top() == 4)

  s.push(7);
  ASSERT(s.top() == 7);

  s.pop();
  ASSERT(s.top() == 4)

  s.pop();
  ASSERT(s.top() == 2)

  s.pop();
  ASSERT(s.top() == 1)

  s.pop();
  ASSERT(s.top() == 0)

  s.pop();

  ASSERT(s.empty())

  s.pop();

  int error = false;
  try {
    int x = s.top();
  }
  catch (std::exception&) {
    error = true;
  }

  ASSERT(error == true);

  return 0;
}