7道经典栈、队列、堆的题目-使用队列实现栈,栈实现队列_出队


7道经典栈、队列、堆的题目-使用队列实现栈,栈实现队列_数据结构_02


栈是一种 后进先出(last in - first out, LIFO)的数据结构,栈内元素从顶端压入(push),从顶端弹出(pop)。一般我们用数组或者链表来实现栈,但是这篇文章会来介绍如何用队列来实现栈。队列是一种与栈相反的 先进先出(first in - first out, FIFO)的数据结构,队列中元素只能从 后端(rear)入队(push),然后从 前端(front)端出队(pop)。两个队列,压入 - O(n), 弹出 - O(1) 修改push操作

7道经典栈、队列、堆的题目-使用队列实现栈,栈实现队列_出队_03


每次压入的数据保证总处于队列顶端

7道经典栈、队列、堆的题目-使用队列实现栈,栈实现队列_leetcode_04


7道经典栈、队列、堆的题目-使用队列实现栈,栈实现队列_数据_05

两个队列,压入 -O(1), 弹出 -O(n)

压入:新元素总是从队列后端入队,同时队列的后端也是栈的栈顶top元素。

弹出:使用另一个临时队列,将数据队列中的元素除队尾的元素都存入临时队列中,然后弹出最后的数据,再将数据从临时队列存储到数据队列中。

7道经典栈、队列、堆的题目-使用队列实现栈,栈实现队列_出队_06

class MyStack {
public:
/** Initialize your data structure here. */
MyStack() {

}

/** Push element x onto stack. */
void push(int x) {
data.push(x);
topdata = x;
}

/** Removes the element on top of the stack and returns that element. */
int pop() {
int times = data.size();
std::queue<int> tem;
while(times >1)
{
tem.push(data.front());
if(times == 2) topdata = data.front();
data.pop();
times--;
}

int tem_data = data.front();
data.pop();

while(!tem.empty())
{
data.push(tem.front());
tem.pop();
}

return tem_data;
}

/** Get the top element. */
int top() {
return topdata;
}

/** Returns whether the stack is empty. */
bool empty() {
return data.empty();
}
private:
std::queue<int> data;
int topdata;
};

/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/

方法三 (一个队列, 压入 - O(n), 弹出 - O(1))
压入:每次压入队列,然后循环取出队列首元素,并压入尾部,一直到新压入的元素处于队列的首部。
利用了队列的出口和入口不同

class MyStack {
public:
/** Initialize your data structure here. */
MyStack() {

}

/** Push element x onto stack. */
void push(int x) {
int times = data.size();
data.push(x);
while(times--)
{
data.push(data.front());
data.pop();
}
}

/** Removes the element on top of the stack and returns that element. */
int pop() {
int tem_data = data.front();
data.pop();
return tem_data;
}

/** Get the top element. */
int top() {
return data.front();
}

/** Returns whether the stack is empty. */
bool empty() {
return data.empty();
}
private:
std::queue<int> data;
};

/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/

7道经典栈、队列、堆的题目-使用队列实现栈,栈实现队列_leetcode_07


7道经典栈、队列、堆的题目-使用队列实现栈,栈实现队列_数据_08


队列是一种 先进先出(first in - first out, FIFO)的数据结构,队列中的元素都从后端(rear)入队(push),从前端(front)出队(pop)。 实现队列最直观的方法是用链表,但在这篇文章里我会介绍另一个方法 - 使用栈。 栈是一种 后进先出(last in - first out, LIFO)的数据结构,栈中元素从栈顶(top)压入(push),也从栈顶弹出(pop)。 为了满足队列的 FIFO 的特性,我们需要用到两个栈,用它们其中一个来反转元素的入队顺序,用另一个来存储元素的最终顺序。使用两个栈 入队 - O(n), 出队 - O(1)

7道经典栈、队列、堆的题目-使用队列实现栈,栈实现队列_出队_09


7道经典栈、队列、堆的题目-使用队列实现栈,栈实现队列_数据_10


7道经典栈、队列、堆的题目-使用队列实现栈,栈实现队列_数据_11

使用两个栈 入队 - O(1),出队 - 摊还复杂度 O(1)

入队(push):新元素总是压入 s1 的栈顶,同时我们会把 s1 中压入的第一个元素赋值给作为队首元素的 front 变量。

7道经典栈、队列、堆的题目-使用队列实现栈,栈实现队列_数据_12


JAVA

private Stack<Integer> s1 = new Stack<>();
private Stack<Integer> s2 = new Stack<>();

// Push element x to the back of queue.
public void push(int x) {
if (s1.empty())
front = x;
s1.push(x);
}

出队(pop):根据栈 LIFO 的特性,s1 中第一个压入的元素在栈底。为了弹出 s1 的栈底元素,我们得把 s1 中所有的元素全部弹出,再把它们压入到另一个栈 s2 中,这个操作会让元素的入栈顺序反转过来。通过这样的方式,s1 中栈底元素就变成了 s2 的栈顶元素,这样就可以直接从 s2 将它弹出了。一旦 s2 变空了,我们只需把 s1 中的元素再一次转移到 s2 就可以了。

// Removes the element from in front of queue.
public void pop() {
if (s2.isEmpty()) {
while (!s1.isEmpty())
s2.push(s1.pop());
}
s2.pop();
}

7道经典栈、队列、堆的题目-使用队列实现栈,栈实现队列_leetcode_13


7道经典栈、队列、堆的题目-使用队列实现栈,栈实现队列_出队_14

class MyQueue {
public:
/** Initialize your data structure here. */
MyQueue() {

}

/** Push element x to the back of queue. */
void push(int x) {
if(s1.empty()) front = x;
s1.push(x);
}

/** Removes the element from in front of queue and returns that element. */
int pop() {
int tem;
if(s2.empty()){ //s2为空
//s1不为空,将s1中数据压入s2中,从而使得s2中数据顺序和队列中一致
while(!s1.empty())
{
tem = s1.top();
s1.pop();
s2.push(tem);
}
//s2.pop();
// return tem;
} //else{ //s2作为输出栈输出
tem = s2.top();
s2.pop();
return tem;
//}
}

/** Get the front element. */
int peek() {
if(!s2.empty()){ //输出队列中有数据,则队列头元素在s2中
return s2.top();
}else{
return front; //否则在s1的栈底
}
}

/** Returns whether the queue is empty. */
bool empty() {
return s1.empty() && s2.empty();
}
private:
std::stack<int> s1; //输入栈
std::stack<int> s2; //输出栈
int front;
};