1、自定义栈获取栈元素最小值(getMin)
1.1 简单描述
自定义一个栈的元素,实现获得最小元素的方法:getMin
1.2 思路:
- 调用两个Java栈集合,一个数据栈dataStack,一个辅助栈helpStack
- 压栈操作:同时压入,data栈正常压入,help栈:
a:如果没有元素,就压入新元素
b:如果有元素,小于help栈顶元素,就压入新元素
c:如果大于或者等于help栈顶元素,就重复压入栈顶元素
(始终保持help栈顶元素是data栈里面的最小元素) - 弹栈操作:一起弹
- 获取最小值:获取help栈的栈顶元素
1.3 具体实现代码:
package cn.nupt.sort;
import java.util.Stack;
public class Stack_getMin {
/**
* @Description: 自定义栈,实现getMin,即找到栈中最小值的方法
*
* @author PizAn
* @date 2019年1月27日 上午11:45:48
*
*/
public static class MyStack {
// 注:如果你自定义的类的名字和你所引用的相同,那么会强制带上前缀
// 比如这里的类名如果也是Stack,下面就不能再引用java.util.Stack;需要加上前缀
// 1、建立两个栈(用Java自带的栈集合)一个是dataStack,一个是helpStack
private Stack<Integer> dataStack;
private Stack<Integer> helpStack;
public MyStack() {
this.dataStack = new Stack<Integer>();
this.helpStack = new Stack<Integer>();
}
// 压栈
public void push(Integer obj) {
// data栈直接压
dataStack.push(obj);
// help栈需要判断一下,如果栈里没有数,就把第一个数压入,如果data栈里面新来的数比help栈顶(即最小的数)小,就压入
// 如果大于或者等于,就重复压入相同的数
if (helpStack.isEmpty()) { // 如果,help栈为空,直接将新数放进去
helpStack.push(obj);
} else if (obj >= helpStack.peek()) { // help栈不为空,且新数大于等于help栈的栈顶元素,重复压入栈顶元素
helpStack.push(helpStack.peek());
} else { // 新数小于栈顶元素,压入新数(始终保持help栈里面是data栈中最小的元素)
helpStack.push(obj);
}
}
// 弹栈
public Integer pop() { // 弹栈的话,两个栈一起弹
if (dataStack.isEmpty()) {
throw new ArrayIndexOutOfBoundsException("The Stack is empty!");
}
Integer popNum = dataStack.pop();
helpStack.pop();
return popNum;
}
// 获得栈顶元素,返回data栈的栈顶元素
public Integer peek() {
if (dataStack.isEmpty()) {
throw new ArrayIndexOutOfBoundsException("The Stack is empty!");
}
return dataStack.peek();
}
// 获得栈的最小元素,也就是获得help栈的栈顶元素(因为help栈的栈顶一直都是data栈的最小元素)
public Integer getMin() {
if (dataStack.isEmpty()) {
throw new ArrayIndexOutOfBoundsException("The Stack is empty!");
}
return helpStack.peek();
}
}
}
2、队列模拟栈
2.1 简单描述
用队列模拟栈的实现,包括压栈push、弹栈pop、获得栈顶元素peek
2.2 思路:
- 调用两个Java队列集合,一个数据队列dataQueue,一个辅助队列helpQueue
(因为queue再Java里面只有接口,这里是用linkedList实现的) - 压栈操作:全部add到dataQueue里面
- 弹栈操作:因为栈是先进后出,队列是先进先出,所以先将dataQueue中的前N-1个元素全部add到helpQueue里面(留下一个屁股),然后把这个屁股”弹“出去,然后helpQueue和dataQueue互换姓名,重复上面的卖屁股操作
- 获取栈顶元素:和pop一样,不过拿到屁股之后还要再装回去
2.3 具体实现代码:
package cn.nupt.sort;
import java.util.LinkedList;
import java.util.Queue;
public class QueueToStack {
/**
* @Description: 用队列模拟栈
*
* @author PizAn
* @date 2019年1月27日 下午3:08:03
*
*/
public static class MyStack {
// 1、建立两个Java自带队列,一个放数据,一个是辅助队列
private Queue<Integer> dataQueue;
private Queue<Integer> helpQueue;
public MyStack() { // 构造函数,因为queue只有接口,这里底层是用 LinkedList实现的
this.dataQueue = new LinkedList<Integer>();
this.helpQueue = new LinkedList<Integer>();
}
// 压栈操作:全部压入dataQueue
public void push(Integer obj) {
dataQueue.add(obj);
}
// 弹栈操作
public Integer pop() {
if (dataQueue.isEmpty()) {
throw new ArrayIndexOutOfBoundsException("The Stack is empty!");
}
while (dataQueue.size() > 1) {
helpQueue.add(dataQueue.poll());
}
Integer res = dataQueue.poll();
//交换两个队列的姓名
swap();
return res;
}
// 拿到栈顶元素
public Integer peek() {
if (dataQueue.isEmpty()) {
throw new ArrayIndexOutOfBoundsException("The Stack is empty!");
}
while (dataQueue.size() > 1) {
helpQueue.add(dataQueue.poll());
}
Integer res = dataQueue.poll();
helpQueue.add(res); // 因为这里是拿到栈顶元素就行了,所以将这个元素还和其他元素一样放到help栈里
swap();
return res;
}
private void swap() {
Queue<Integer> temp = dataQueue;
dataQueue = helpQueue;
helpQueue = temp;
}
}
}
3、栈模拟队列
3.1 简单描述
用栈实现队列,包括进队列push、出队列poll、获得队列第一个元素peek
3.2 思路:(其实想一下,只要用两个栈,就能把先进后出变成先进先出了,"倒"一下就行了)
-
调用两个Java栈集合,一个专管进队列pushStack,一个专管出队列 pollStack
-
进队列操作:全部压到pushStack里面
-
出队列操作:将pushStack里面的元素全部“倒”到 pollStack里面,然后从pollStack里面拿元素,这个里面有两点要注意:
a:只有在pollStack为空的时候才能倒入元素
b:pushStack倒元素到pollStack里面一定要一次性倒完,不要有剩余 -
获取队列首元素:直接调用pollStack的peek方法
3.3 具体实现代码:
package cn.nupt.sort;
import java.util.Stack;
/**
* @Description: 用栈实现队列
*
* @author PizAn
* @date 2019年1月27日 下午4:11:02
*
*/
public class StackToQueue {
// 建立两个栈,其中一个只管push(进队列),另一个只管poll(出队列),将push里面的元素全部“倒”到poll里面,不就
// 可以实现头朝下脚朝上,先进后出变成先进先出了么
// 不过这里“倒”有个技巧,你只能在pop为空的时候倒,并且push要全部倒完才行
private Stack<Integer> pushStack;
private Stack<Integer> pollStack;
public StackToQueue() {
this.pushStack = new Stack<Integer>();
this.pollStack = new Stack<Integer>();
}
// 进队列操作
public void push(Integer obj) {
pushStack.push(obj);
}
// 出队列操作
public Integer poll() {
if (pushStack.isEmpty() && pollStack.isEmpty()) {
throw new ArrayIndexOutOfBoundsException("The queue is empty!");
} else if (pollStack.isEmpty()) { // 条件1:poll栈是空的
while (!pushStack.isEmpty()) { // 条件2:push栈不是空的
pollStack.push(pushStack.pop());
}
}
Integer res = pollStack.pop();
return res;
}
public Integer peek() {
if (pushStack.isEmpty() && pollStack.isEmpty()) {
throw new ArrayIndexOutOfBoundsException("The queue is empty!");
} else if (pollStack.isEmpty()) { // 条件1:poll栈是空的
while (!pushStack.isEmpty()) { // 条件2:push栈不是空的
pollStack.push(pushStack.pop());
}
}
return pollStack.peek();
}
}