这里写目录标题
学习栈和队列需要先熟悉栈和队列相应的性质和各自的方法。
栈
栈(Stack)是一种常见的数据结构,它遵循先进后出(Last-In-First-Out,LIFO)的原则。可以将栈看作是一叠盘子,只能从最顶层放入和取出元素,无法直接访问或修改中间位置的元素。
栈的主要操作包括以下方法:
-
push(E element)
:将元素压入栈顶。新的元素被添加到栈的顶部,成为新的栈顶元素。 -
pop()
:弹出栈顶元素并返回。栈顶元素被移除,并且返回被移除的元素。 -
peek()
:返回栈顶元素,但不进行移除。只返回栈顶的元素,不对栈进行修改。 -
isEmpty()
:检查栈是否为空。如果栈中没有任何元素,返回 true;否则返回 false。
栈的实现可以使用数组或链表等数据结构。在实际编程中,常用的栈实现方式包括使用数组或使用链表,也可以使用现有的栈数据结构(如C++中的std::stack、Java中的java.util.Stack)。
栈常用于解决与后续处理(如函数调用、表达式求值、回溯算法等)相关的问题,也可用于处理需要遵循 LIFO 原则的其他情况。
队列
队列(Queue)是一种常见的数据结构,它遵循先进先出(First-In-First-Out,FIFO)的原则。可以将队列看作是一条排队等候的队伍,新的元素被添加到队列的末尾,而从队列中取出元素的操作总是从队列的头部进行。
队列的主要操作包括以下方法:
-
add(E element)
:将元素添加到队列的末尾。如果队列已满则抛出异常。 -
offer(E element)
:将元素添加到队列的末尾。如果队列已满则返回false
。 -
remove()
:移除并返回队列头部的元素。如果队列为空则抛出异常。 -
poll()
:移除并返回队列头部的元素。如果队列为空则返回null
。 -
element()
:返回队列头部的元素,但不进行移除操作。如果队列为空则抛出异常。 -
peek()
:返回队列头部的元素,但不进行移除操作。如果队列为空则返回null
。 -
int size()
:返回队列中元素的数量。该方法返回队列的当前大小,即队列中包含的元素个数。 -
boolean isEmpty()
:检查队列是否为空。如果队列中没有任何元素,即队列为空,返回 true;否则返回 false。.
队列的实现可以使用数组、链表或其他数据结构。在实际编程中,常用的队列实现方式包括使用数组、使用链表或使用现有的队列数据结构(如C++中的std::queue
、Java中的java.util.Queue
)。
队列常用于处理需要遵循 FIFO 原则的场景,例如任务调度、消息传递、广度优先搜索等。它可以确保元素按照添加的顺序被处理,并且适用于多线程环境下的并发操作。
232. 用栈实现队列
class MyQueue {
private Stack<Integer> stackIn;
private Stack<Integer> stackOut;
public MyQueue() {
stackIn = new Stack<>();
stackOut = new Stack<>();
}
public void push(int x) {
stackIn.push(x);
}
public int pop() {
int peek = peek();
stackOut.pop();
return peek;
}
public int peek() {
if(!stackOut.isEmpty()){
return stackOut.peek();
}
while(!stackIn.isEmpty()){
stackOut.push(stackIn.pop());
}
return stackOut.peek();
}
public boolean empty() {
if(stackIn.isEmpty() && stackOut.isEmpty()){
return true;
}
return false;
}
}
225. 用队列实现栈
双队列模拟栈
定义两个队列A与B,其中A是模拟的栈,B队列是备份队列。在添加元素时,先把元素添加到队列B中,然后再循环将A队列的值都出队并添加到B队列末尾。这样,每次添加元素之后,B队列中的元素都是以出栈的顺序排列的。循环结束后,将B队列赋值给A队列,B队列置为空,等待下一次添加元素。
这样处理过后,A队列中的元素都是以栈的出栈顺序排列的,如果要获取栈顶元素或出栈,直接执行A队列的方法即可。
class MyStack {
Queue<Integer> Queue1;
Queue<Integer> Queue2;
public MyStack() {
Queue1 = new LinkedList<Integer>();
Queue2 = new LinkedList<Integer>();
}
public void push(int x) {
Queue2.offer(x);
while(!Queue1.isEmpty()){
Queue2.offer(Queue1.poll());
}
Queue<Integer> temp = Queue1;
Queue1 = Queue2;
Queue2 = temp;
}
public int pop() {
return queue1.poll();
}
public int top() {
return queue1.peek();
}
public boolean empty() {
return queue1.isEmpty();
}
}
用一个队列实现栈
将上述方法进行优化,我们可以不需要备份队列B,元素入栈时,将它添加到队列A队尾,然后再将之前的所有元素依次出队并添加到队尾,此时元素就已排列成出栈的顺序。然后直接对队列A进行栈操作即可。
class MyStack {
Queue<Integer> queue;
public MyStack() {
queue = new LinkedList<Integer>();
}
public void push(int x) {
int size = queue.size();
queue.offer(x);
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();
}
}