栈和队列
1.根据入栈出栈规律,判断顺序是否合理
实现思路:
直接使用栈试错,其中inOutOrder为原始数据,outOrder为需要判断的顺序,inOutOrder根据outOrder判断入栈出栈规则
public boolean isOutOrder(int[] inOutOrder, int[] outOrder) {
if (inOutOrder == null || outOrder == null || inOutOrder.length != outOrder.length) {
return false;
}//判断边界值
Stack<Integer> stack = new Stack<>();
int i = 0, j = 0;//i用于inOutOrder遍历,j用于outOrder的遍历
while (i < inOutOrder.length - 1) {
if (stack.isEmpty()) {
stack.push(inOutOrder[i++]);
}//判断stack是否为null,为null时,需要进栈
while (outOrder[j] != stack.peek() && i != inOutOrder.length) {
stack.push(inOutOrder[i++]);
}//前者判断最顶上的数据与outOrder数组中的数组是否相等,后者为了控制边界值(即i不会越界)
while (outOrder[j] == stack.peek()) {
stack.pop();
j++;
if (j == outOrder.length - 1) {
return true;
}//当outOrder中所有数据都试错过之后那么自然返回true
if (stack.isEmpty()) {
stack.push(inOutOrder[i++]);
}//依旧为了控制边界值,当所有数据全部弹出后,inOutOrder之后的数据入栈
}
}
return false;//当i已经超过inOutOrder数组范围,明显栈弹出规律为false
}
2.用栈结构实现队列结构
实现思路:
应该注意两个栈相互导数据的时机,比如
stackPush中有数据,就直接倒入stackPop
poll() 执行之前应把所有数据倒入stackPop
add() 之前需要stackPop中没有数据
public class TwoStackQueue<T> {
Stack<T> stackPush;
Stack<T> stackPop;
public TwoStackQueue() {
this.stackPush = new Stack<>();
this.stackPop = new Stack<>();
}
public void PushToPop() {//该方法用于stackPush往stackPop中导数据
if (stackPop.isEmpty()) {//此时将stackPush中的所有数据都倒入stackPop
while (!stackPush.isEmpty()) {
stackPop.push(stackPush.pop());
}
}
}
public void add(T value) {
stackPush.push(value);//先把数据存入stackPush
PushToPop();//将存入的数倒入stackPop
}
public T poll() {
if (stackPush.isEmpty() && stackPop.isEmpty()) {
throw new RuntimeException("栈空!");
}
PushToPop(); //弹出之前需要保证stackPush中没有数据
return stackPop.pop();
}
public T peek(){
if (stackPop.isEmpty() && stackPush.isEmpty()){
throw new RuntimeException("栈空!");
}
PushToPop(); //查看之前需要保证stackPush中没有数据
return stackPop.peek();
}
}
3.用队列结构实现栈结构
实现思路:
模拟入栈:添加数据时,往有数据的那个队列插入数据
模拟出栈:将有数据的那个队列中数据全导入另一个队列,直到只剩下一个数据为止,把最后剩下的数据返回并删除,模拟队列出栈
public class TwoQueueStack<T> {
LinkedList<T> q1;//使用链表模拟队列,采用头插尾删法
LinkedList<T> q2;
public TwoQueueStack() {
q1 = new LinkedList<>();
q2 = new LinkedList<>();
}
public void add(T value) {//添加数据时,往有数据的那个队列插入数据
if (!q1.isEmpty()) {
q1.addFirst(value);
} else {
q2.addFirst(value);
}
}
public T poll() {
if (q1.isEmpty() && q2.isEmpty()) {//判断两个队列是否都为空,都为空的话,抛出队列空异常
throw new RuntimeException("队空!");
}
if (!q1.isEmpty() && q2.isEmpty()) {
while (q1.size() > 1) {//将有数据的那个队列中数据全导入另一个队列,直到只剩下一个数据为止
q2.addFirst(q1.removeLast());
}
return q1.removeFirst();//把最后剩下的数据返回并删除,模拟队列出栈
}
if (q1.isEmpty() && !q2.isEmpty()) {
while (q2.size() > 1) {
q1.addFirst(q2.removeLast());
}
return q2.removeFirst();
}
return null;
}
}
4.实现一个具有getMin功能的栈
实现思路:
使用两个栈,一个原始数据栈stackData,一个最小值栈stackMin
pubs时,当stackMin为空时,直接将这个值压入栈,当value小于时,压入这个值,当大于等于stackMin栈顶元素时,压入栈顶元素
pop时,两个栈同时弹出,返回stackData栈顶元素
getMin时,直接返回stackMin栈顶元素
public class MyStack {
Stack<Integer> stackData;
Stack<Integer> stackMin;
public MyStack() {
this.stackData = new Stack<>();
this.stackMin = new Stack<>();
}
public void pubs(int value) {
if (stackMin.isEmpty()) {//栈为空时,直接把这个数压入栈中
stackMin.push(value);
} else if (value < stackMin.peek()) {//如果这个数比最小数栈顶小,压入这个数
stackMin.push(value);
} else {//剩下的就是比最小数栈顶大于或等于的,那么直接压入栈顶元素
stackMin.push(stackMin.peek());
}
stackData.push(value);//data栈同步压入
}
public int pop() {
if (stackMin.isEmpty()) {//判断边界值
throw new RuntimeException("栈空!");
}
stackMin.pop();//两个栈同步弹出,data栈栈顶元素返回
return stackData.pop();
}
public int getMin() {
if (stackMin.isEmpty()) {
throw new RuntimeException("栈空!");
}
return stackMin.peek();//返回最小值栈顶值
}
}