在学习完栈和队列后,栈的特征是先进后出,队列的特征是先进先出,因此可以利用该性质,利用两个栈实现队列的操作,利用两个队列实现栈的操作。
目录
利用栈实现队列
队列的定义:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的性质。入队列:进行插入操作的一端称为队尾;出队列:进行删除操作的一端称为队头
队列中有哪些方法?
如何利用栈实现队列 ?
需要定义出两个栈来实现队列,首先将要存入的元素放入第一个栈stack1中,当要出队时,就将stack1中的元素出栈存入到stack2中,则此时stack2的出栈顺序即为队列的出队顺序.
初始化
初始化两个栈,stack1和stack2,stack1主要用来入队操作,stack2用来实现出队操作
public class MyQueue {
Stack<Integer> stack1;
Stack<Integer> stack2;
//构造方法
public MyQueue() {
this.stack1 = new Stack<>();
this.stack2 = new Stack<>();
}
}
入队列
入队操作统一将元素存入stack1中,存入后如下图所示
具体代码:
//入队操作
public void push(int x) {
this.stack1.push(x);
}
判断队列是否为空
队列判空操作只需要判断两个栈是否都为空即可.
//队列是否为空
public boolean empty() {
return stack1.empty() && stack2.empty();
}
弹出队头元素
要弹出队头元素,需要将stack1中的元素按照栈的出栈顺序存入到stack2中,此时stack2中的出栈顺序即为队列的出队顺序,具体如下图所示:
注意: 在将stack1中元素存储stack2的过程中,一定是出栈操作,而不能是取栈顶元素操作。
//弹出队头元素
public int pop() {
if(empty()) {
return -1;
}
if(stack2.empty()) {
while(!stack1.empty()) {
int val = stack1.pop();
stack2.push(val);
}
}
return stack2.pop();
}
获取队头元素
获取队头元素依旧是将stack1中元素出栈存入stack2中,如果之后还需要将元素入队,则直接插入栈stack中,但不对stack2进行操作,只有当stack2为空时,再将栈stack1中元素出栈插入到栈stack2中.
//获取队头元素
public int peek() {
if(empty()) {
return -1;
}
if(stack2.empty()) {
while(!stack1.empty()) {
int val = stack1.pop();
stack2.push(val);
}
}
return stack2.peek();
}
栈实现队列完整代码
import java.util.*;
public class MyQueue {
Stack<Integer> stack1;
Stack<Integer> stack2;
//构造方法
public MyQueue() {
this.stack1 = new Stack<>();
this.stack2 = new Stack<>();
}
//入队操作
public void push(int x) {
this.stack1.push(x);
}
//弹出队头元素
public int pop() {
if(empty()) {
return -1;
}
if(stack2.empty()) {
while(!stack1.empty()) {
int val = stack1.pop();
stack2.push(val);
}
}
return stack2.pop();
}
//获取队头元素
public int peek() {
if(empty()) {
return -1;
}
if(stack2.empty()) {
while(!stack1.empty()) {
int val = stack1.pop();
stack2.push(val);
}
}
return stack2.peek();
}
//队列是否为空
public boolean empty() {
return stack1.empty() && stack2.empty();
}
}
利用队列实现栈
栈的定义:栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入或删除的一端称为栈顶,另一端称为栈底。栈中的元素遵循后进先出(先进后出)原则。压栈:栈的插入操作称为压栈/进栈/入栈,入栈在栈顶进行;出栈:栈的删除操作称为出栈,出栈在栈顶进行.
栈中有哪些方法?
如何利用队列实现栈?
创建两个队列,que1和que2,每次进行入栈时将元素存入为空的一个队列中,当要进行出栈或者取栈顶元素操作时,首先将非空队列中Size - 1个元素入队至当前为空的队列中,之后非空队列剩下的元素即为栈顶元素.
初始化
创建两个队列que1和que2来实现栈的操作
public class MyStack {
private Queue<Integer> que1;
private Queue<Integer> que2;
//构造方法
public MyStack() {
que1 = new LinkedList<>();
que2 = new LinkedList<>();
}
}
判断栈是否为空
只需判断两个队列是否都为空,若都为空,则栈为空.
//判断栈是否为空
public boolean isEmpty() {
if(que1.isEmpty() && que2.isEmpty()) {
return true;
}
return false;
}
入栈操作
在进行入栈操作前,需要判断两个队列哪个为空,将要入栈的元素插入到不为空的那个队列中,如果两个队列都为空,默认插入到第一个队列que1中.
例如下图,目前栈中已经存入1、2、3,若要继续存入4,则需判断哪个栈不为空,将其插入至不为空的栈中.
//入栈操作
public void pop(int x) {
if(!que1.isEmpty()) {
que1.offer(x);
} else if (!que2.isEmpty()) {
que2.offer(x);
} else {
//当两个队列都为空时,默认放到第一个队列中
que1.offer(x);
}
}
出栈操作
要进行出栈操作,首先将非空队列中的size-1个元素入队至第二个队列中,如下图所示:
之后que1中剩余的一个元素即为栈顶元素,将该元素出队即可实现栈的出栈操作.
//出栈操作
public int pop() {
if(isEmpty()) {
return -1;
}
if(!que1.isEmpty()) {
int size = que1.size();
for (int i = 0; i < size-1; i++) {
int x = que1.poll();
que2.offer(x);
}
//返回剩下的元素
return que1.poll();
} else {
int size = que2.size();
for (int i = 0; i < size-1; i++) {
int x = que2.poll();
que1.offer(x);
}
//返回剩下的元素
return que2.poll();
}
}
获取栈顶元素
利用队列实现获取栈顶元素操作与出栈操作基本思想一致,只不过获取栈顶元素操作未将元素删除,而是保存下来后返回.
如下图所示:
此时x保存的数据即为栈顶元素,返回该元素即可.
//获取栈顶元素
public int top() {
if(isEmpty()) {
return -1;
}
if(!que1.isEmpty()) {
int size = que1.size();
int x = -1;
for (int i = 0; i < size; i++) {
x = que1.poll();
que2.offer(x);
}
//返回剩下的元素
return x;
} else {
int size = que2.size();
int x = -1;
for (int i = 0; i < size; i++) {
x = que2.poll();
que1.offer(x);
}
//返回剩下的元素
return x;
}
}
队列实现栈完整代码
import java.util.LinkedList;
import java.util.Queue;
public class MyStack {
private Queue<Integer> que1;
private Queue<Integer> que2;
//构造方法
public MyStack() {
que1 = new LinkedList<>();
que2 = new LinkedList<>();
}
//判断栈是否为空
public boolean isEmpty() {
if(que1.isEmpty() && que2.isEmpty()) {
return true;
}
return false;
}
//入栈操作
public void pop(int x) {
if(!que1.isEmpty()) {
que1.offer(x);
} else if (!que2.isEmpty()) {
que2.offer(x);
} else {
//当两个队列都为空时,默认放到第一个队列中
que1.offer(x);
}
}
//出栈操作
public int pop() {
if(isEmpty()) {
return -1;
}
if(!que1.isEmpty()) {
int size = que1.size();
for (int i = 0; i < size-1; i++) {
int x = que1.poll();
que2.offer(x);
}
//返回剩下的元素
return que1.poll();
} else {
int size = que2.size();
for (int i = 0; i < size-1; i++) {
int x = que2.poll();
que1.offer(x);
}
//返回剩下的元素
return que2.poll();
}
}
//获取栈顶元素
public int top() {
if(isEmpty()) {
return -1;
}
if(!que1.isEmpty()) {
int size = que1.size();
int x = -1;
for (int i = 0; i < size; i++) {
x = que1.poll();
que2.offer(x);
}
//返回剩下的元素
return x;
} else {
int size = que2.size();
int x = -1;
for (int i = 0; i < size; i++) {
x = que2.poll();
que1.offer(x);
}
//返回剩下的元素
return x;
}
}
}