利用数组实现栈和队列
用数组实现栈
public class ArrayStack {
private Integer[] arr;
private Integer size;
// 初始化
public ArrayStack(int initSize) {
if (initSize < 0) {
throw new IllegalArgumentException("the init size is less than 0");
}
arr = new Integer[initSize];
size = 0;
}
// 顶
public Integer peek() {
if (size == 0) {
return null;
}
return arr[size-1];
}
// 添加元素
public void push(int obj) {
if (size == arr.length) {
throw new ArrayIndexOutOfBoundsException("the queue is full");
}
arr[size++] = obj;
}
// 弹出元素
public Integer pop() {
if (size == 0) {
throw new ArrayIndexOutOfBoundsException("the queue is empty");
}
return arr[--size];
}
}
用数组实现队列
- start和end的策略:只要到底了,就会跳到开头
public class ArrayQueue {
private Integer[] arr;
// 用三个变量就能很快写出来,而不需要扣细节
// start变量表示如果弹出一个元素,应该是哪一个位置上的
private Integer start;
// end变量表示如果添加一个元素,应该放在哪一个位置上
private Integer end;
// 利用size来约束start和end, start和end之间是解耦的
private Integer size;
public ArrayQueue(Integer initSize) {
if (initSize < 0) {
throw new IllegalArgumentException("the init size is less than 0");
}
arr = new Integer[initSize];
start = 0;
end = 0;
size = 0;
}
public Integer peek() {
if (size == 0) {
return null;
}
return arr[start];
}
public void push (Integer obj) {
if (size == arr.length) {
throw new ArrayIndexOutOfBoundsException("the queue is full");
}
size++;
arr[end] = obj;
// end只要到底了,就会跳到开头,所以需要一个size来维护长度
end = end == arr.length-1 ? 0 : end + 1;
}
public Integer poll() {
if (size == 0) {
throw new ArrayIndexOutOfBoundsException("the queue is empty");
}
size--;
Integer tmp = start;
// end只要到底了,就会跳到开头,所以需要一个size来维护长度
start = start == arr.length - 1 ? 0 : start + 1;
return arr[tmp];
}
}
实现特殊的栈
实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作
要求:
- pop、push、getMin操作的时间复杂度都是O(1)
- 设计的栈类型可以使用现成的栈结构
public class _30_包含min函数的栈 {
/** initialize your data structure here. */
// 两个栈:一个做数据栈,一个做最小栈
// 用额外空间:多维护一个最小栈,来保存最小值在栈顶;最小堆结构也可以实现
private Stack<Integer> dataStack;
private Stack<Integer> minStack;
public _30_包含min函数的栈() {
minStack = new Stack<Integer>();
dataStack = new Stack<Integer>();
}
public void push(int x) {
dataStack.push(x);
// 最小栈存数据,这里有等于号
if(minStack.isEmpty() || minStack.peek() >= x){
minStack.push(x);
}
}
public void pop() {
// 比较的是Integer,需要用equals
// 如果pop正好是最小栈的最小值,应该pop出去,因为这个数据已不存在
if(dataStack.pop().equals(minStack.peek())){
minStack.pop();
}
}
public int top() {
return dataStack.peek();
}
public int min() {
return minStack.peek();
}
}
// 另外一种设计; push的时候如果大,则push栈peek的数,这样pop的时候就不需要判断
public void push(int x) {
dataStack.push(x);
// 最小栈存数据,这里有等于号
if(minStack.isEmpty()){
minStack.push(x);
} else if (minStack.peek() >= x){
minStack.push(x);
} else {
minStack.push(minStack.peek());
}
}
public void pop() {
dataStack.pop();
minStack.pop();
}
仅用栈结构实现队列
public class _09_两个栈实现队列 {
// 输入栈,输出栈
private Stack<Integer> inStack;
private Stack<Integer> outStack;
public _09_两个栈实现队列() {
inStack = new Stack<>();
outStack = new Stack<>();
}
// 在队列尾部插入元素;
public void appendTail(int value) {
inStack.push(value);
}
// 在删除队列头部元素;
public int deleteHead() {
// 当输出栈为空的时候,才能进行转换数据操作
if(outStack.isEmpty()){
while(!inStack.isEmpty()){
outStack.push(inStack.pop());
}
}
// 输出栈输出数据
return outStack.isEmpty() ? -1 : (int)outStack.pop();
}
}
仅用队列结构实现栈
public class TwoQueue {
Queue<Integer> a = new LinkedList<Integer>();
Queue<Integer> b = new LinkedList<Integer>();
//a入栈
public void push(int node) {
a.offer(node);
while(!b.isEmpty()){
b.offer(a.poll());
}
Queue temp=a;
a=b;
b=a;
}
public int pop() {
return b.poll();
}
}