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