文章目录
- 1.什么是栈?
- 2.栈的应用场景
- 3.栈的具体实现
- 3.1 基于简单数组的实现
- 3.2 动态数组的实现
- 3.3 链表的实现
- 3.4 Java动态数组实现栈结构
- 4 项目地址
1.什么是栈?
栈是一个有序的线性表,只能在栈顶进行操作插入和删除操作。所以也叫先进后出表。
2.栈的应用场景
- 符号匹配
- 中缀表达式转换为后缀表达式
- 计算后缀表达式
- 实现函数调用
- 求范围误差
- 网页浏览器中已访问页面的历史纪录
- 文本编辑器中的撤销序列
- 作为算法辅助数据结构(二叉树的非递归遍历)
3.栈的具体实现
3.1 基于简单数组的实现
顾名思义,就是用数组实现栈的应用
性能表:
操作 | 时间复杂度 | 空间复杂度 |
---|---|---|
push() | O(1) | O(n) |
pop() | O(1) | O(1) |
size() | O(1) | O(1) |
isEmpty() | O(1) | O(1) |
isFull() | O(1) | O(1) |
deleteStack() | O(1) | O(1) |
3.2 动态数组的实现
它其实就是在简单数组基础上实现重复倍增来实现的:
以上面的简单数组实现为基础,增加一个倍增方法:
/*** 栈空间扩增方法*/private void doubleStack() {int[] newArray = new int[capacity*2];System.arraycopy(array,0,newArray,0,capacity);capacity = capacity*2;array = newArray;}
性能表:
操作 | 时间复杂度 | 空间复杂度 |
---|---|---|
push() | O(1) | O(n) |
pop() | O(1) | O(1) |
size() | O(1) | O(1) |
isEmpty() | O(1) | O(1) |
isFull() | O(1) | O(1) |
deleteStack() | O(1) | O(1) |
3.3 链表的实现
使用链表实现栈,通过在链表的表头插入元素的方式实现push,删除链表的表头节点实现pop.
但,使用它还需要实现节点的构造,相比数组麻烦些,而且链表不太符合栈的顺序特性,
且它的性能表如下:
操作 | 时间复杂度 | 空间复杂度 |
---|---|---|
push() | O(1) | O(n) |
pop() | O(1) | O(1) |
size() | O(1) | O(1) |
isEmpty() | O(1) | O(1) |
isFull() | O(1) | O(1) |
deleteStack() | O(n) | O(1) |
相比之下它的deleteStack复杂度比动态数组大。所以推荐使用动态数组实现栈。
3.4 Java动态数组实现栈结构
package course.p5_stack;/*** 栈的基础实现* 栈比较适合使用数组实现,因为使用数组实现栈的push,pop的时间复杂度都为O(1),且操作简单*/
public class ArrayStack {/*** 存储栈顶元素的索引*/private int top;/*** 栈的空间大小,默认起始为10*/private int capacity = 10;/*** 存储栈元素的数组*/private int[] array;/*** 无参构造方法*/public ArrayStack() {array = new int[capacity];top = -1;}/*** 定义大小构造方法* @param a 定义栈的大小*/public ArrayStack(int a) {capacity = a;array = new int[a];top = -1;}/*** 判断此栈是否为空* @return true--空 false--不空*/public boolean isEmpty() {return top == -1;}/*** 判断栈是否已满* @return*/public boolean isStackFull() {return top == capacity-1;}/*** 将数据压入栈中* @param data*/public void push(int data) {if(isStackFull()) {doubleStack();}array[++top] = data;}/*** 弹出栈顶元素* @return*/public int pop() {if(isEmpty()) {System.out.println("Stack is Empty!");return -1;}else{return array[top--];}}/*** 删除栈*/public void deleteStack() {top = -1;array = null;capacity = 0;}/*** 栈空间扩增方法*/private void doubleStack() {int[] newArray = new int[capacity*2];System.arraycopy(array,0,newArray,0,capacity);capacity = capacity*2;array = newArray;}
}
测试方法编写:
package course.p5_stack;import org.junit.Assert;
import org.junit.Test;import java.util.Optional;
import java.util.Random;
import java.util.Stack;public class StackTest {private final Stack<Integer> stackRight = new Stack<>();@Testpublic void stackTest(){ArrayStack stack = new ArrayStack();for (int i=0;i<1000;i++){boolean active = new Random().nextBoolean();if(active){stack.push(i);stackRight.push(i);}else {Assert.assertEquals(stackRight.isEmpty(),stack.isEmpty());if(!stackRight.isEmpty()){Assert.assertEquals(Optional.ofNullable(stackRight.pop()),Optional.ofNullable(stack.pop()));}}}}}
运行结果:(没有任何报错,测试通过)
Process finished with exit code 0
4 项目地址
https://gitee.com/yan-jiadou/algorithm-study/blob/master/algorithmStudy/src/main/java/course/p5_stack/StackTest.java