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

Algorithm 使用队列实现堆栈-最佳复杂性,algorithm,stack,queue,time-complexity,Algorithm,Stack,Queue,Time Complexity,我想知道是否有一种方法可以实现一个堆栈,根据需要使用尽可能多的队列来推送和弹出O(1)中的数据。 如果没有任何O(1)算法,那么最好的复杂度是多少?您可以使用线性时间推送和恒定时间推送制作堆栈 给定一个具有函数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,

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

您可以使用线性时间推送和恒定时间推送制作堆栈

给定一个具有函数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)
编辑:不需要临时队列管理器的替代解决方案:

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)

您可以使用线性时间推送和固定时间弹出创建堆栈

给定一个具有函数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)
编辑:不需要临时队列管理器的替代解决方案:

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)

如果允许在队列中递归定义队列,则可以使用以下命令进行O(1)推送/弹出操作:

代码:

结果是一个递归形成的堆栈

如果
[1,2]
表示一个堆栈,其中
出列([1,2])
将返回
1
。然后将数据结构(如果
1
然后
3
然后
6
推到堆栈上)如下所示:

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

如果允许在队列中递归定义队列,则可以使用以下命令进行O(1)推送/弹出操作:

代码:

结果是一个递归形成的堆栈

如果
[1,2]
表示一个堆栈,其中
出列([1,2])
将返回
1
。然后将数据结构(如果
1
然后
3
然后
6
推到堆栈上)如下所示:

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

这里是一个用O(1)推和POP函数实现的堆栈的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;
}
#包括
#包括
#包括
#包括
#定义断言(x)\
如果(!(x)){\
std::cout push(val);
m_tail=tail;
}
void pop(){
如果(m_头){
删除m_头;
m_head=重新解释(m_tail->front());
m_tail->pop();
std::queue*tail=reinterpret_cast(m_tail->front());
删除m_tail;
m_tail=tail;
}
}
常量T&top()常量{
如果(!m_头){
抛出std::runtime_错误(“检索顶部元素时出错;堆栈为空”);
}
返回m_head->front();
}
bool empty(){
回来!你的头;
}
私人:
std::队列*m_头;
std::queue*m_tail;
};
int main(){
堆栈s;
s、 pop();
s、 推(0);
断言(s.top()==0);
s、 推(1);
断言(s.top()==1);
s、 推(2);
断言(s.top()==2);
s、 推(3);
断言(s.top()==3);
s、 pop();
断言(s.top()==2)
s、 推(4);
断言(s.top()==4);
s、 推(5);
断言(s.top()==5);
s、 推(6);
断言(s.top()==6);
s、 pop();
断言(s.top()==5)
s、 pop();
断言(s.top()==4)
s、 推(7);
断言(s.top()==7);
s、 pop();
断言(s.top()==4)
s、 pop();
断言(s.top()==2)
s、 pop();
断言(s.top()==1)
s、 pop();
断言(s.top()==0)
s、 pop();
断言(s.empty())
s、 pop();
int error=false;
试一试{
int x=s.top();
}
捕获(标准::异常&){
错误=真;
}
断言(错误==true);
返回0;
}

> P>这里是一个用O(1)推和POP函数的堆栈的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;
}
#包括
#包括
#包括
#包括
#定义断言(x)\
如果(!(x)){\
std::cout push(val);
m_tail=tail;
}
void pop(){
如果(m_头){
删除m_头;
m_head=重新解释(m_tail->front());
m_tail->pop();
std::queue*tail=reinterpret_cast(m_tail->front());
删除m_tail;
m_tail=tail;
}
}
常量T&top()常量{
如果(!m_头){
抛出std::runtime_错误(“检索顶部元素时出错;堆栈为空”);
}
返回m_head->front();
}
bool empty(){
回来!你的头;
}
私人:
std::队列*m_头;
std::queue*m_tail;
};
int main(){
堆栈s;
s、 pop();
s、 推(0);
断言(s.top()==0);
s、 推(1);
断言(s.top()==1);
s、 推(2);
断言(s.top()==2);
s、 推(3);
断言(s.top()==3);
s、 pop();
断言(s.top()==2)
s、 推(4);
断言(s.top()==4);
s、 推(5);
断言(s.top()==5);
s、 推(6);
断言(s.top()==6);
s、 pop();
断言(s.top()==5)
s、 pop();
断言(s.top()==4)
s、 推(7);
断言(s.top()==7);
s、 pop();
断言(s.top()==4)
s、 pop();
断言(s.top()==2)
s、 pop();
断言(s.top()==1)
s、 pop();
断言(s.top()==0)
s、 pop();
断言(s.empty())
s、 pop();
int error=false;
试一试{
int x=s.top();
}
捕获(标准::异常&){
错误=真;
}
断言(错误==true);
返回0;
}

你所说的O(1)是什么意思?我的意思是算法所花费的时间不应该依赖于n-堆栈的大小。它必须是恒定的算法做什么所花费的时间?我不这么认为。你为什么要这么做?直观地说,我倾向于说O(n)是最好的情况。如果你可以使用数组实现O(1)堆栈,你也可以使用一个由1个元素组成的队列数组,但那是毫无意义的。你能更好地定义这个问题吗?是否允许使用数组或变量,或者解决方案必须完全由队列组成?O(1)是什么意思?我的意思是,算法所花费的时间不应依赖于堆栈的大小。它必须是恒定的算法做什么所花费的时间?我不这么认为。你为什么要这么做?直观地说,我倾向于说O(n)是最好的情况。如果你可以使用数组实现O(1)堆栈,你也可以使用一个由1个元素组成的队列数组,但那是毫无意义的。你能更好地定义这个问题吗?您是否允许使用数组或变量,或者解决方案必须完全由队列组成。。是O(n)。但我无法想象有比这更好的了!谢谢你的回答:)好的。。是O(n)。但我无法想象