文章目录
前言
栈(Stack)和队列(Queue)是两种常见的数据结构,它们在程序设计和算法中有着广泛的应用。栈和队列都是特定顺序的数据集合,但它们的操作方式和特性略有不同,因此在某些情况下,需要相互实现的能力。
有时候在解决问题时,需要将栈转换为队列或者队列转换为栈,以满足特定的操作顺序需求。例如,在某些算法中需要使用栈来辅助实现队列的功能,或者使用队列来实现栈的功能。这种转换可以通过两种数据结构的基本操作来实现,是算法设计中的常见技巧之一。
在接下来的讨论中,我们可以探讨如何实现栈和队列的相互转换,以及如何利用它们来解决各种实际问题。
一、思路
1.栈实现队列
(1).两个栈的定义:
in 栈:用于处理入队操作。新元素总是被压入 in 栈。
out 栈:用于处理出队和取队头操作。当需要从队列中移除元素或查看队头时,元素将从这个栈弹出。
(2).入队操作 (push):
新元素直接压入 in 栈。
出队操作 (pop):
如果 out 栈为空,则将 in 栈中的所有元素逐个弹出并压入 out 栈。这样,元素的顺序就被反转,使得最早进入 in 栈的元素现在位于 out 栈的顶部,这样可以实现队列的 FIFO 行为。如果 out 栈不为空,直接从 out 栈弹出元素。
(3)获取队头元素 (peek):
和 pop 类似,如果 out 栈为空,需要将 in 栈中的所有元素逐个弹出并压入 out 栈。
然后返回 out 栈的顶部元素,但不弹出它。
检查队列是否为空 (isEmpty):
只需检查 in 和 out 两个栈是否都为空。如果两个栈都为空,则队列为空。
2.队列实现栈
(1)Push 操作:
每次调用 push 方法时,将新元素添加到 queue2。
然后将 queue1 中的所有元素移动到 queue2。
最后交换 queue1 和 queue2,这样 queue1 中的元素顺序就变成了栈所需要的顺序。
(2)Pop 操作:
pop 方法直接从 queue1 中移除并返回元素,因为 queue1 中的顺序已经是栈的顺序。
Top 操作:
top 方法返回 queue1 的队首元素,这就是栈顶元素。
(3)Empty 操作:
empty 方法返回 queue1 是否为空。
二、详细代码
代码如下(示例):
import java.util.LinkedList;
import java.util.Queue;
class MyStack {
private Queue<Integer> queue;
public MyStack() {
queue = new LinkedList<>();
}
public void push(int x) {
// Get the current size of the queue
int size = queue.size();
// Add the new element to the queue
queue.offer(x);
// Rotate the queue to make the newly added element at the front
for (int i = 0; i < size; i++) {
queue.offer(queue.poll());
}
}
public int pop() {
return queue.poll();
}
public int top() {
return queue.peek();
}
public boolean empty() {
return queue.isEmpty();
}
public static void main(String[] args) {
MyStack stack = new MyStack();
stack.push(1);
stack.push(2);
System.out.println(stack.top()); // Output: 2
System.out.println(stack.pop()); // Output: 2
System.out.println(stack.top()); // Output: 1
System.out.println(stack.empty()); // Output: false
}
}
import java.util.LinkedList;
import java.util.Queue;
class MyStack {
private Queue<Integer> queue1;
private Queue<Integer> queue2;
public MyStack() {
queue1 = new LinkedList<>();
queue2 = new LinkedList<>();
}
// Push element x onto stack.
public void push(int x) {
// Add element to queue2
queue2.offer(x);
// Move all elements from queue1 to queue2
while (!queue1.isEmpty()) {
queue2.offer(queue1.poll());
}
// Swap the names of queue1 and queue2
Queue<Integer> temp = queue1;
queue1 = queue2;
queue2 = temp;
}
// Removes the element on top of the stack and returns that element.
public int pop() {
// Remove and return the top element from queue1
return queue1.poll();
}
// Get the top element.
public int top() {
// Return the top element without removing it
return queue1.peek();
}
// Return whether the stack is empty.
public boolean empty() {
// Check if queue1 is empty
return queue1.isEmpty();
}
public static void main(String[] args) {
MyStack stack = new MyStack();
stack.push(1);
stack.push(2);
System.out.println(stack.top()); // Output: 2
System.out.println(stack.pop()); // Output: 2
System.out.println(stack.top()); // Output: 1
System.out.println(stack.empty()); // Output: false
}
}
总结
1.用栈实现队列:使用两个栈来实现队列的功能,其中一个栈用于入队操作,另一个栈用于出队操作:这种方法保证了入队和出队操作的均摊时间复杂度为 O(1),虽然在某些情况下需要一定的操作来移动元素。
2. 用队列实现栈
使用两个队列来实现栈的功能,其中一个队列用于主要存储栈的元素,另一个队列在需要时辅助操作;这种实现方式同样保证了栈的基本操作的均摊时间复杂度为 O(1),虽然在某些情况下需要移动元素。
通过这种相互实现的方式,可以更深入地理解栈和队列的内部工作原理,加深对数据结构和算法的理解和运用。