概述
- 栈是一个先入后出的有序列表,和队列正好相反
- 栈是限制线性表中的元素的插入和删除都只能在线性表的同一段进行的一种特殊线性表。允许插入和删除的一端称作栈顶,另一端作为固定的一段,称为栈底
- 根据栈的定义可知,最先放入栈中的元素在栈底,最后入栈的元素在栈顶,而出栈是正好相反,最后放入的元素最先出栈
栈的应用
- 子程序的调用:在调用子程序钱,会先将下一个指令的地址存到堆栈中,知道子程序执行完后再将地址取出,从而回到原来的程序中
- 处理递归调用:和子程序调用类似,只是除了下一个指令的地址外,也将参数、局域变量等跟随指令一起存入堆栈中
- 表达式的转换:中缀表达式转后追表达式与求值
- 二叉树的遍历
- 图的深度优先搜索算法
逻辑结构示意图
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/8c4af54a29866e4bcdb513e3482c3f20.png)
代码实现
数组方式
class ArrayStack{
private int maxSize;
private int[] array;
private int top = -1;
public ArrayStack(int maxSize) {
this.maxSize = maxSize;
this.array = new int[maxSize];
}
public void push(int num) {
if(isFull()) {
System.out.println("栈已满");
return;
}
array[++top]=num;
}
public int pop() {
if(isEmpty()) {
throw new RuntimeException("栈中没有任何元素");
}
return array[top--];
}
public int peek() {
if(isEmpty()) {
throw new RuntimeException("栈中没有任何元素");
}
return array[top];
}
public void list() {
if(isEmpty()) {
System.out.println("栈为空");
return;
}
int helper = top;
while(helper!=-1) {
System.out.println(array[helper--]);
}
}
public boolean isFull() {
return top==maxSize-1;
}
public boolean isEmpty() {
return top==-1;
}
}
链表方式
class SingleLinkedListStack {
private SingleLinkedList data;
private Node top;
public SingleLinkedListStack() {
data = new SingleLinkedList();
top = data.getHead();
}
public void push(Node node) {
top.next = node;
top = top.next;
}
public Node pop() {
if (isEmpty()) {
throw new RuntimeException("栈为空");
}
Node helper = data.getHead();
while (helper.next != top) {
helper = helper.next;
}
Node res = top;
helper.next = top.next;
top = helper;
return res;
}
public Node peek() {
if (isEmpty()) {
throw new RuntimeException("栈为空");
}
return top;
}
public void list() {
if (isEmpty()) {
System.out.println("栈为空");
return;
}
Stack<Node> stack = new Stack<>();
Node helper = data.getHead();
while (helper.next != null) {
stack.add(helper.next);
helper = helper.next;
}
while (!stack.isEmpty()) {
System.out.println(stack.pop());
}
}
public boolean isEmpty() {
return top == data.getHead();
}
}
class SingleLinkedList {
private Node head = new Node(0, "", "");
public Node getHead() {
return this.head;
}
public void add(Node node) {
Node helper = head;
while (true) {
if (helper.next != null) {
helper = helper.next;
} else {
break;
}
}
helper.next = node;
}
public void list() {
if (head.next == null) {
System.out.println("链表为空");
return;
}
Node helper = head.next;
while (true) {
System.out.println(helper);
if (helper.next != null) {
helper = helper.next;
} else {
break;
}
}
}
public void addByOrder(Node node) {
Node helper = head;
boolean isExist = false;
while (true) {
if (helper.next == null) {
break;
}
if (helper.next.no > node.no) {
break;
} else if (helper.next.no == node.no) {
isExist = true;
break;
}
helper = helper.next;
}
if (isExist) {
System.out.printf("编号为%d节点已存在\n", node.no);
} else {
node.next = helper.next;
helper.next = node;
}
}
public void update(Node node) {
Node helper = head;
boolean isExist = false;
while (true) {
if (helper.next == null) {
break;
} else if (helper.next.no == node.no) {
isExist = true;
break;
}
helper = helper.next;
}
if (isExist) {
helper.next.name = node.name;
helper.next.nickName = node.nickName;
} else {
System.out.printf("没有找到编号为%d的节点\n", node.no);
}
}
public void delete(int no) {
Node helper = head;
boolean isExist = false;
while (true) {
if (helper.next == null) {
break;
} else if (helper.next.no == no) {
isExist = true;
break;
}
helper = helper.next;
}
if (isExist) {
helper.next = helper.next.next;
} else {
System.out.printf("编号为%d的节点不存在", no);
}
}
}
class Node {
int no;
String name;
String nickName;
Node next;
public Node(int no, String name, String nickName) {
this.no = no;
this.name = name;
this.nickName = nickName;
this.next = null;
}
@Override
public String toString() {
return "no=" + no + "\tname=" + name + "\tnickName=" + nickName;
}
}
栈解决表达式求值问题
public static int calculator(String s) {
int length = s.length();
ArrayStack numStack = new ArrayStack(length);
ArrayStack oprStack = new ArrayStack(length);
for (int i = 0; i < length; i++) {
int ch = s.charAt(i);
if (isOper(ch)) {
if (oprStack.isEmpty()) {
oprStack.push(ch);
} else {
if (priority(ch) < priority(oprStack.peek())) {
while (!oprStack.isEmpty()&&priority(ch) < priority(oprStack.peek())) {
numStack.push(cal(numStack.pop(), numStack.pop(), oprStack.pop()));
}
oprStack.push(ch);
} else {
oprStack.push(ch);
}
}
} else {
ch = ch - 48;
if (i != length - 1) {
while (true) {
int next = s.charAt(i + 1);
if (isOper(next)) {
break;
} else {
ch = ch * 10 + next - 48;
i++;
if (i == length - 1) {
i++;
break;
}
}
}
}
numStack.push(ch);
}
}
while (!oprStack.isEmpty()) {
numStack.push(cal(numStack.pop(), numStack.pop(), oprStack.pop()));
}
return numStack.pop();
}
public static boolean isOper(int ch) {
return ch == '+' || ch == '-' || ch == '*' || ch == '/';
}
public static int priority(int opr) {
if (!isOper(opr)) {
throw new RuntimeException("不是一个操作符");
}
if (opr == '+' || opr == '-') {
return 0;
}
return 1;
}
public static int cal(int num1, int num2, int oper) {
switch (oper) {
case '+':
return num1 + num2;
case '-':
return num2 - num1;
case '*':
return num1 * num2;
case '/':
return num2 / num1;
}
return 0;
}