一,栈的简单认识
栈是一种线性数据结构,但是与数组不同的是,只能从栈顶存入元素,或者删除元素.详细的操作下会阐述.
(栈是一种后进先出的数据结构)
二,栈的具体实现.
Stack<E>
1,void push(E) //栈顶插入元素
2,E pop () //栈顶删除元素,返回值时删除的栈顶元素
3,E peek() //获取栈顶元素,但是并不删除
4,int getSize() //获取索引
5,boolean isEmpty() //判断栈是否为空
三,时间复杂度分析
Stack<E>
1,void push(E) //栈顶插入元素 0(1) 均摊
2,E pop () //栈顶删除元素,返回值时删除的栈顶元素 0(1) 均摊
3,E peek() //获取栈顶元素,但是并不删除 0(1)
4,int getSize() //获取索引 0(1)
5,boolean isEmpty() //判断栈是否为空 0(1)
四,以数组为底层逻辑,实现栈的各个功能.
1,利用抽象类封装
public interface Stack<T> { // 入栈/压栈 void push(T ele); // 出栈/弹栈 T pop(); // 查看栈中元素的个数 int getSize(); // 判断栈是否为空 boolean isEmpty(); // 查看栈顶元素 T peek(); }
2,对功能进行实现
// 数组栈:以数组作为栈的底层容器 public class ArrStack<T> implements Stack<T> { // 底层数据结构 private MyArray2<T> data; // 栈中实际存放元素的数量 private int size; public ArrStack() { this.data = new MyArray2<>(); this.size = 0; } @Override public void push(T ele) { this.data.addTail(ele); this.size++; } @Override public T pop() { T result = this.data.removeFromTail(); if(result != null){ this.size--; } return result; } @Override public int getSize() { return this.size; } @Override public boolean isEmpty() { return this.size == 0; } @Override public T peek() { return null; //return this.data.findLastElement(); } }
五,栈的优势和用处.
在 Java 中,栈相比数组的优势;
-
动态大小: 栈可以动态调整大小,当需要存储更多元素时,栈可以动态扩展大小,而数组在创建时大小是固定的,需要实现自己的扩展逻辑。
-
支持常规操作: 栈提供了 push(入栈) 和 pop(出栈) 操作,使得对数据的操作更加方便。
栈可以解决一些常见的问题,包括但不限于:
-
表达式求值: 栈可以用于表达式求值,对于中缀表达式,可以通过将中缀表达式转换为后缀表达式来实现求值。
-
括号匹配: 栈可以用于检查表达式中的括号是否匹配。遍历表达式,当遇到左括号时将其压入栈中,遇到右括号时弹出栈顶元素进行匹配。
-
深度优先搜索(DFS): 栈可以用于实现深度优先搜索算法,通过栈的先入后出的特性来探索图的深层节点。
-
逆波兰表达式求值: 栈可以用于逆波兰表达式(后缀表达式)的求值,通过遍历表达式,遇到数字入栈,遇到操作符弹出栈顶元素进行计算再将结果入栈,直到整个表达式遍历完毕。
总的来说,栈在解决具有“后进先出”特性的问题时非常有效,并且能够简化算法的实现过程。