“栈”
- 栈是一个先入后出(FILO——First In Last Out)的有序列表。
- 栈(stack)是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端,为变化的一端,称为栈顶(Top),另一端为固定的一端,称为栈底(Bottom)。
- 最先放入栈中元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元 素最先删除,最先放入的元素最后删除
图解入栈与出栈:
应用场景:
- 子程序的调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以 回到原来的程序中。
- 处理递归调用:和子程序的调用类似,只是除了储存下一个指令的地址外,也将参数、区域变量等数据存入堆 栈中。
- 表达式的转换[中缀表达式转后缀表达式]与求值(实际解决)。
- 二叉树的遍历。
- 图形的深度优先(depth 一 first)搜索法
数组模拟栈
思路:
- 定义top表示栈顶
- 入栈:
top++
stack[top] = data
- 出栈
int value = stack[top]
top - -
代码实现
public class ArrayStack {
private int maxsize; // 栈的大小
private int[] stack; // 数组模拟栈
private int top = -1; //栈顶,-1表示没有数据
public ArrayStack(int maxsize) {
this.maxsize = maxsize;
this.stack = new int[maxsize];
}
public boolean isFull(){
return maxsize-1 == top;
}
public Boolean isEmpty(){
return top == -1;
}
/**
* @Description: push 入栈
*/
public void push(int num){
if (isFull()){
System.out.println("栈已满");
return;
}
top++;
stack[top] = num;
}
/**
* @Description: 出栈
*/
public int pop(){
if (isEmpty()){
throw new RuntimeException("栈空");
}
int value = stack[top];
top--;
return value;
}
/**
* @Description: 展示
*/
public void show(){
if (isEmpty()){
System.out.println("栈空~~~");
return;
}
for (int i = top; i >= 0; i--) {
System.out.println("stack["+i+"] = " + stack[i]);
}
}
}
测试数组模拟栈:
public class TestStack {
public static void main(String[] args) {
ArrayStack arrayStack = new ArrayStack(3);
String key = "";
boolean loop = true; // 控制菜单循环
Scanner scanner = new Scanner(System.in);
while (loop){
System.out.println("show:显示栈");
System.out.println("exit:退出栈");
System.out.println("push:入栈");
System.out.println("pop:出栈");
key = scanner.next();
switch (key){
case "show":
arrayStack.show();
break;
case "exit":
scanner.close();
loop = false;
break;
case "push":
System.out.println("请输入一个数");
arrayStack.push(scanner.nextInt());
break;
case "pop":
try {
int pop = arrayStack.pop();
System.out.println("pop = " + pop);
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
default:
break;
}
}
System.out.println("退出程序");
}
}
链表模拟栈
思路:
- 一样使用top来指向栈顶
- 使用单向链表存储数据,每次入栈都将数据存储插入第一个节点
图解:
链表模拟队列代码:
节点:
public class LinkListStcakNode {
private int no;
private String name;
private String nckName;
private LinkListStcakNode next;//下一个节点
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNckName() {
return nckName;
}
public void setNckName(String nckName) {
this.nckName = nckName;
}
public LinkListStcakNode getNext() {
return next;
}
public void setNext(LinkListStcakNode next) {
this.next = next;
}
public LinkListStcakNode(int no, String name, String nckName) {
this.no = no;
this.name = name;
this.nckName = nckName;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nckName='" + nckName + '\'' +
'}';
}
}
操作栈:
public class LinkLiskeStack {
private int maxsize;
private LinkListStcakNode head = new LinkListStcakNode(0,"",""); // 链表模拟栈
private int top = -1;
public LinkLiskeStack(int maxsize) {
this.maxsize = maxsize;
}
public Boolean isFull(){
return top == maxsize-1;
}
public Boolean isEmpty(){
return top == -1;
}
/**
* @Description: push 添加
*/
public void push(LinkListStcakNode node){
if (isFull()){
System.out.println("栈满");
return;
}
// 插入到第一个节点
node.setNext(head.getNext());
head.setNext(node);
top++;
}
/**
* @Description: 出栈
*/
public LinkListStcakNode pop(){
if (isEmpty()){
throw new RuntimeException("栈空~~~");
}
// 找到第一个节点
LinkListStcakNode node = head.getNext();
// 将头节点的next指向出栈节点的下一个节点
head.setNext(head.getNext());
top--;
return node;
}
public void show(){
if (isEmpty()){
System.out.println("栈空");
}
LinkListStcakNode temp = head.getNext();
while (temp != null){
System.out.println(temp);
temp = temp.getNext();
}
}
}
测试链表模拟栈
public class TestStack {
public static void main(String[] args) {
LinkLiskeStack linkLiskeStack = new LinkLiskeStack(3);
LinkListStcakNode node1 = new LinkListStcakNode(1, "宋江", "及时雨");
LinkListStcakNode node2 = new LinkListStcakNode(2, "卢俊义", "玉麒麟");
LinkListStcakNode node3 = new LinkListStcakNode(3, "吴用", "智多星");
System.out.println("入栈");
linkLiskeStack.push(node1);
linkLiskeStack.push(node2);
linkLiskeStack.push(node3);
linkLiskeStack.show();
System.out.println("出栈");
LinkListStcakNode pop = linkLiskeStack.pop();
System.out.println("pop = " + pop);
}
}