目录
何为栈:
栈:棚也,字典对其释译之一是储存货物或供旅客住宿的房屋,在计算机中栈可以看作是数据歇脚的地方,对数据进行暂时存储,数据入栈相当于办理入住向JVM申请空间,当程序运行结束时,相关数据就会从栈中弹出释放空间,就像数据退房离开了一样。
概念:一个只允许在固定一端进行插入和删除元素操作的特殊线性表(一个前驱一个后继)。遵循后进先出(LIFO)原则
前驱:栈中位于其下方的元素。
后继:栈中位于其上方的元素。
Java 标准库中的栈 Stack
继承自 Vector 类
from Java Documentation
1. empty() 判断栈是否为空
2. peek() 查看栈顶元素
3. pop() 出栈(从栈顶开始)并将其从栈中删除
4. push() 入栈
5. clear() 清空栈中所有元素
6. search() 从栈顶开始搜索指定元素在栈中的位置,找到则返回其距离栈顶的位置(栈顶为1),如果未找到则返回-1。
7. size() 获取栈中有效元素
//import java.util.Stack; //public class Test { //public static void main(String[] args) { // 使用标准库的栈 //Stack<String> stack = new Stack<>(); //入栈 //stack.push("aa"); //stack.push("bb"); //stack.push("cc"); //此时栈中 //cc //bb //aa //取栈顶元素 //String top = stack.peek(); //System.out.println(top); //出栈 //String s = stack.pop(); //System.out.println(s); //s = stack.pop(); //System.out.println(s); //s = stack.pop(); //System.out.println(s); //} //}// 运行结果
cc // 栈顶元素
cc
bb
aa
模拟实现栈
基于数组:
讲数组的尾部看作栈顶,从这里压入新元素,同样从这里出,实现后进先出的效果
// 基于数组
public class MyStack {
private String[] arr;
private int size;
public MyStack(){
arr = new String[1000];
size = 0;
}
public MyStack(int capacity) {
arr = new String[capacity];
size = 0;
}
public void resize(){
// 创建一个更长的数组
String[] newArr = new String[arr.length * 2];
// 复制原数组
for(int i = 0; i < arr.length; i++){
newArr[i] = arr[i];
}
// 用新数组替换旧数组
arr = newArr;
}
// 入栈
// elem element 元素
public void push(String elem){
if(size == arr.length){
// 扩容
resize();
}
// 实现一个尾插
arr[size] = elem;
size++;
}
// 出栈
public String pop(){
if(size == 0){
throw new RuntimeException("Stack is empty");
}
// 取出栈顶元素
String elem = arr[size - 1];
size--;
return elem;
}
// 获取栈顶元素
public String peek(){
if(size == 0){
throw new RuntimeException("Stack is empty");
}
String elem = arr[size - 1];
return elem;
}
public static void main(String[] args) {
// 测试
MyStack stack = new MyStack();
stack.push("aaa");
stack.push("bbb");
stack.push("ccc");
System.out.println(stack.peek());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.peek());
}
}
基于顺序表:
借助 ArrayList
类的方法来实现栈的入栈、出栈、查看栈顶元素等基本操作。ArrayList
是动态数组,可自动扩容,所以无需像基于数组实现栈那样手动处理扩容问题。
import java.util.ArrayList;
import java.util.Scanner;
// 基于ArrayList
public class MyStack2 {
private ArrayList<String> stack;
public MyStack2(){
stack = new ArrayList<>();
}
// size
public int size(){
return stack.size();
}
// 判断是否为空
public boolean isEmpty(){
return stack.isEmpty();
}
// 入栈
public void push(String elem){
// 尾插
stack.add(elem);
}
// 出栈
public String pop(){
// 判断是否为空
if(!isEmpty()){
throw new RuntimeException("Stack is empty");
}
// 尾删
return stack.remove(stack.size() - 1);
}
// 查看栈顶元素
public String peek(){
// 判断是否为空
if(!isEmpty()){
throw new RuntimeException("Stack is empty");
}
// 获取最后一个元素
return stack.get(stack.size() - 1);
}
public static void main(String[] args) {
MyStack2 stack = new MyStack2();
stack.push("a");
stack.push("b");
stack.push("c");
System.out.println("Top element: " + stack.peek());
System.out.println("Popped element: " + stack.pop());
System.out.println("Stack size: " + stack.size());
}
}
基于链表:
链表知道头节点便可得到整个链表,可以直接 将头节点作为栈顶
package stack;
import java.util.Scanner;
// 定义链表节点类
class Node {
String elem;
Node next;
public Node(String elem) {
this.elem = elem;
this.next = null;
}
}
// 基于链表实现的栈类
public class MyStack3 {
private Node head;
private int size;
// 构造函数,初始化栈
public MyStack3() {
head = null;
size = 0;
}
// 判断栈是否为空
public boolean isEmpty() {
return head == null;
}
// 获取栈的大小
public int size() {
return size;
}
// 入栈操作
public void push(String elem) {
Node newNode = new Node(elem);
newNode.next = head;
head = newNode;
size++;
}
// 出栈操作
public String pop() {
if (isEmpty()) {
throw new RuntimeException("Stack is empty, cannot pop.");
}
String elem = head.elem;
head = head.next;
size--;
return elem;
}
// 查看栈顶元素
public String peek() {
if (isEmpty()) {
throw new RuntimeException("Stack is empty, cannot peek.");
}
return head.elem;
}
public static void main(String[] args) {
MyStack3 stack = new MyStack3();
stack.push("a");
stack.push("b");
stack.push("c");
System.out.println("Top element: " + stack.peek());
System.out.println("Popped element: " + stack.pop());
System.out.println("Stack size after pop: " + stack.size());
}
}
此处栈本质上就是一个顺序表 / 链表,但是在其基础上做出了限制,禁止了顺序表 / 链表的各种增删改查操作,只支持三个操作,入栈、出栈、取栈顶元素。可以认为其就是只支持尾插、尾删、获取尾部元素的顺序表或者链表
栈的练习
答案正在骑码来的路上 ......
To be continued
欢迎评论✨
或许你会有一天怀念,可是我已不再— 小镇姑娘 DT