简单数组栈的局限性
栈的最大空间必须预先声明并且不能改变,试图对一个满栈执行入栈操作会产生一个针对简单数组这种
特定实现方式的异常
动态数组实现
-
方案一 栈满时,每次将数组的大小增加1
Push() 数组的容量增加1
Pop() 数组的大小减1
方法存在的问题:这种增加数组大小的方法开销太大,具体分析如下,例如,当n=1时候,执行 push的过程为,新建一个大小为2的数组,复制原数组中的所有元素到新数组中,在新数组末端添
加元素,当n=2时,执行push操作的过程为,新建一个大小为3的数组,复制原数组中的所有元素到
新数组中,在新数组末端添加新元素
以此类推,当n = n-1时,执行push操作的过程为,新建一个大小为n的数组,复制原来数组中的所有元素到新数组中,在新数组末端添加新元素,在执行n次push操作后,总时间开销T(n)(复制操作的数量)为1+2+…+n≈O(N*2) -
重复倍增
使用数组倍增技术来提高性能,如果数组空间已满,新建一个比原数组空间大一倍的数组,然后复制元素,采用这种处理方法,执行n次push操作的时间开销为n,假设从n=1开始,一直增大到n=32,按照1,2
4,8次序倍增
倍增操作需执行logn次
n次push操作总时间开销T(n)为1+2+4+8+…+n/4+n/2+n=n(1+1/2+1/4+…+1/n)≈n(2)≈2n≈O(n)
T(n)为O(n),一次push操作的平摊时间为O(1)
代码实现
/**
* 基于动态数组的栈实现
*/
public class DynArrayStack {
private int top;
private int capacity;
private int[] array;
public DynArrayStack(int capacity) {
this.capacity = capacity;
array = new int[capacity];
top = -1;
}
public DynArrayStack() {
this(1);
}
/**
* 判断栈非空
*
* @return
*/
public boolean isEmpty() {
return top == -1;
}
/**
* 判断栈是否满元素
*/
public boolean isStackFull() {
return top == (array.length - 1);
}
/**
* 压栈操作
*/
public void push(int data) {
//如果当前栈满元素,扩容
if (isStackFull()) {
doubleStack();
}
}
/**
* 数组扩容
*/
private void doubleStack() {
int[] newArray = new int[capacity * 2];
System.arraycopy(array, 0, newArray, 0, capacity);
capacity = capacity * 2;
array = newArray;
}
/**
* 出栈
*/
public int pop() {
if (isEmpty()) {
throw new RuntimeException("Stack is Empty!");
} else {
return array[top--];
}
}
/**
* 初始化栈
*/
public void deleteStack() {
top = -1;
}
}