1、栈
1.1 介绍
- 栈是一个先入后出(FILO-First In Last Out)的有序列表。
- 栈(stack)是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端,为变化的一段,称为栈顶(top),另一端为固定的一端,称为栈底(bottom)。
- 最先放入栈中的元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除。
- 入栈push
- 出栈 pop
1.2 应用场景
1)子程序的调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中。
2)处理递归调用:和子程序的调用类似,只是除了储存下一个指令的地址外,也将参数、区域变量等数据存入堆栈中。
3)表达式的转换与求值(实际解决)。
4)二叉树的遍历。
5)图形的深度优先(depth—first)搜索法。
1.3 用数组模拟栈
1.3.1 思路分析
- 定义一个top变量表示栈顶,初始化为-1
- 入栈的操纵,当有数据加入到栈时,
top++;stack[top]=data;
- 出栈的操作,
int value=stack[top];top--;return value;
1.3.2 代码实现
public class ArrayStackDemo {
public static void main(String[] args) {
ArrayStack stack=new ArrayStack(4);
String key="";
boolean loop=true; //控制是否退出菜单
Scanner sc=new Scanner(System.in);
while(loop) {
System.out.println("--------------------界面-----------------");
System.out.println("show:显示栈");
System.out.println("push:添加数据到栈(入栈)");
System.out.println("pop:从栈中取出数据(出栈)");
System.out.println("exit:退出");
System.out.println("请输入你的选择[show|push|pop|exit]:");
key=sc.next();
switch (key) {
case "show":
stack.list();
break;
case "push":
System.out.println("请先输入一个数:");
int value=sc.nextInt();
stack.push(value);
break;
case "pop":
try {
int result=stack.pop();
System.out.println("出栈的数据为:"+result);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case "exit":
sc.close();
loop=false;
break;
default:
break;
}
}
System.out.println("程序退出!");
}
}
//定义一个ArrayStack 表示栈
class ArrayStack{
private int maxSize; //表示栈的大小
private int[] stack; //数组
private int top=-1; //表示栈顶,初始化为-1
//构造器
public ArrayStack(int maxSize) {
this.maxSize = maxSize;
stack=new int[this.maxSize];
}
//栈空
public boolean isEmpty() {
return top==-1;
}
//栈满
public boolean isFull() {
return top==maxSize-1;
}
//入栈
public void push(int value) {
//先判断栈是否已经满了
if(isFull()) {
System.out.println("栈满");
return;
}
top++;
stack[top]=value;
System.out.println("添加成功!");
}
//出栈
public int pop() {
//先判度那栈是否为控股
if(isEmpty()) {
throw new RuntimeException("栈空!");
}
int value=stack[top];
top--;
return value;
}
//遍历栈【从栈顶开始显示数据】
public void list() {
if(isEmpty()) {
System.out.println("栈空,没有数据!");
return;
}
for(int i=top;i>=0;i--) {
System.out.println("stack["+i+"]="+stack[i]);
}
}
}
1.4 用链表模拟栈
1.4.1 思路分析
-
定义一个head变量表示链表头,不表示节点数据,节点编号从1开始。
-
在链表中设置一个变量MaxSize表示模拟栈的大小,编写一个方法getLength()获取有效数据的个数,用于判断是否栈满和节点编号增加。
-
入栈的操纵,当有数据加入到栈时,分为链表为空和不为空时
if(head.next==null) { head.next=newNode; }else { newNode.next=head.next; head.next=newNode; }
-
出栈的操作
Nodes temp=head.next; head.next=head.next.next; return temp;
1.4.2 代码实现
public class LinkedStackDemo {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
LinkedStack stack=new LinkedStack();
String key="";
boolean loop=true; //控制是否退出菜单
while(loop) {
System.out.println("--------------------界面-----------------");
System.out.println("show:显示栈");
System.out.println("push:添加数据到栈(入栈)");
System.out.println("pop:从栈中取出数据(出栈)");
System.out.println("exit:退出");
System.out.println("请输入你的选择[show|push|pop|exit]:");
key=sc.next();
switch (key) {
case "show":
stack.show();
break;
case "push":
sc.nextLine();
//获取长度后加一,保证节点编号不一样
int value=stack.getLength(stack.getHead());
System.out.println("请输入该节点的值:");
String str=sc.nextLine();
Nodes newnode=new Nodes(value+1,str);
stack.push(newnode);
break;
case "pop":
try {
Nodes result=stack.pop();
System.out.println("出栈的信息为:"+result);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case "exit":
sc.close();
loop=false;
break;
default:
break;
}
}
System.out.println("程序退出!");
}
}
//模拟栈
class LinkedStack{
public int MaxSize=5; //设置栈的大小
private Nodes head=new Nodes(0,"");
//获取到head
public Nodes getHead() {
return head;
}
//获取到链表的结点个数(不统计头节点)
public int getLength(Nodes head) {
int length=0;
Nodes temp=head.next;
//没有统计头结点
while(temp!=null) {
length++;
temp=temp.next;
}
return length;
}
//入栈
public void push(Nodes newNode) {
//判满处理
if(getLength(head)==MaxSize) {
System.out.println("当前栈已经满了.");
return;
}
//栈空处理和非空处理
if(head.next==null) {
head.next=newNode;
}else {
newNode.next=head.next;
head.next=newNode;
}
System.out.println("入栈成功!");
}
//出栈
public Nodes pop() {
//判空处理
if(head.next==null) {
throw new RuntimeException("当前栈,为空!");
}
//先存储节点的信息,后删除节点
Nodes temp=head.next;
head.next=head.next.next;
return temp;
}
//显示所有的信息
public void show() {
Nodes temp=head.next;
//判空处理
if(temp==null) {
System.out.println("当前栈,为空!");
return;
}
while(true) {
//判断是否到最后
if(temp==null) {
break;
}
//输出节点的信息
System.out.println(temp);
//将节点后移
temp=temp.next;
}
}
}
//节点
class Nodes{
public int no;
public Nodes next;
public String val;
public Nodes(int no,String val){
this.no=no;
this.val=val;
}
@Override
public String toString() {
return "Node [no=" + no + ", val=" + val + "]";
}