数据结构栈——java

栈是数据结构中最重要的结构之一,也是算法中最爱考的,我们平常写代码的时候习惯了直接用自带的类Stack,直接用里面自带的方法:push、pop、peek等。那你是否自己动手写过一个带基本功能的栈?跟我一起写一下吧!!!
首先先来了解一下栈栈结构其实就是一种线性结构。如果从数据的存储结构来进一步划分,栈结构包括两类。

- 顺序栈结构:即使用一组地址连续的内存单元 依次保存栈中的数据。在程序中,可以定义一个指定大小的结构数组来作为栈,序号为0的元素就是栈底,在定义一个变量top保存栈底的序号即可
- 链式栈结构:即使用链表形式保存栈中各元素的值。链表首部(head引用所指向元素)为栈顶,链表尾部(指向地址为Null)为栈底。
防盗
其中datan是栈顶元素,data1是栈底元素
也就是说保存和取出数据都只能从栈结构的一端进行。从数据的运算角度来分析,栈结构是按照“后进先出(Last In First Out,LIFO)”的原则处理结点的数据。
生活中也有很多栈结构的生动的例子。例如,当仓库中堆放货物时,先来的货物放在里面,后来的货物放在外面;当要取出货物时,总是先取外面的,最后才取里面的货物,也就是后放入的货物先取出。

首先先准备一下数据

创建一个栈结构数据元素的类DATA类里面就是我们要存放的什么样的数据

public class DATA {
    String name;
    int age;
}

我就少写两个,我要存的数据是姓名和年龄。

接下来在创建一个栈结构的类StackType。

public class StackType {
    static final int maxsize=50;//定义一下栈中所存的最大容量
    DATA data[]=new DATA[maxsize];//存放数据元素
    int top;//指向栈顶元素,当top=0时栈为空
    }

第一步初始化栈

在使用顺序栈之前,首先要创建一个空的顺序栈,即初始化顺序栈。
操作步骤为:

  1. 按符号常量SIZE指定的大小申请一片内存空间,用来保存栈中的数据。
  2. 设置栈顶引用的值为0,表示一个空栈
 StackType STInit()//申请栈内存
    {
       StackType p;
       if((p=new StackType())!=null)//如果申请内存成功
       {
           p.top=0;//设置指向栈顶的指针为0
           return p;
       }
       return null;
    }

判断空栈

如果是空栈,则表示栈中没有数据,此时可以进行入栈操作,但不可以进行出栈操作。

boolean StackEmpty(StackType s)//判断栈是否为空,注意方法的返回类型
    {
        boolean f;
        f=(s.top==0);//如果指向栈顶的top等于0那就代表是空栈
        return f;
    }

判断满栈

如果栈为满,则表示该栈结构中不能再入栈,只能出栈。

boolean StackFull(StackType s)//判断栈是否为满
    {
        boolean f;
        f=(s.top==maxsize);//如果top等于我们上面定义的数据存放最大值,那就代表栈满
        return f;
    }

清空栈

清空栈中所有的数据

 void STClear(StackType s)//清空栈
    {
        s.top=0;
    }

在上述代码中,输入参数s是一个指向操作的栈的引用。在程序中,简单的将栈顶引用top设置为0,表示执行清空栈操作。

入栈操作

入栈(Push)是栈结构的基本操作,主要操作是将数据元素保存到栈结构。入栈操作的具体步骤如下:
(1)首先判断栈顶top,如果top>=maxsize,则表示栈满,不能在入栈;否则做以下操作。
(2)设置top=top+1;先将指向栈顶的top加一。
(3)将入栈元素保存到top指向的位置。
代码如下:

//注意返回类型是int如果入栈成功则返回1,反之则返回0
 int PushSt(StackType s,DATA data)//入栈操作 data是要入栈的数据
    {
        if(s.top+1>maxsize)
        {
            System.out.println("栈以满");
            return 0;
        }
        s.data[++s.top]=data;//为什么不是s.top++下面是解释
        //细节:先++再在加过后的top所指的地方按放数据。
        //假设top指的是第三个3,第三个3已经有数据了,就先将top上移然后在存放数据.(这里是解释++s.top)
        return 1;
    }

出栈操作

出栈与入栈相反,其操作是从栈顶弹出一个数据元素,出栈操作的步骤如下:
(1)判断栈顶top,如果top==0,则表示空栈,进行出错处理;否则执行以下操作。
(2)将栈顶引用top所指定的位置元素返回。
(3)设置top=top-1,也就是使栈顶引用减1,指向栈的下一个元素,原来栈顶元素被弹出。
代码如下:

//注意返回类型是DATA出栈的是DATA类型的数据name,age所以返回类型是DATA
 DATA PopSt(StackType s)//出栈操作
    {
        if(s.top==0)
        {
            System.out.println("栈空");
           System.exit(0);//0表示正常退出,其他数字表示非正常退出
        }
        return (s.data[s.top--]);
        //细节:top本来指向第3个,先用3这个数字,先将3这块的数据输出来后再将top--
    }

入栈和出栈有两个细节++s.top和s.top–,大家这么聪明肯定都只带++a和a++的区别

读取结点数据

由于栈结构只能在一端进行出入操作,所以这里的读取操作其实就是读取栈顶的数据。
需要注意的是读结点数据和出栈不同。读结点数据的操作仅仅显示栈顶结点数据的内容,读完该数据还存在栈中,依然是栈顶数据。而出栈操作则将栈顶数据弹出,该数据就不再存在了。
代码如下:

DATA PeekST(StackType s)//读栈顶元素
    {
        if(s.top==0)
        {
            System.out.println("栈空");
            System.exit(0);
        }
        return (s.data[s.top]);
        //不做++或--操作因为只读不取,由于栈特殊操作所以只能读栈顶元素
    }

以上就是一个栈基本操作的各方法,现在我们把它放在一个类里面
代码如下:

public class StackType {
    static final int maxsize=50;
    DATA data[]=new DATA[maxsize];
    int top;
    StackType STInit()//申请栈内存
    {
       StackType p;
       if((p=new StackType())!=null)//如果申请内存成功
       {
           p.top=0;
           return p;
       }
       return null;
    }
    boolean StackEmpty(StackType s)//判断栈是否为空
    {
        boolean f;
        f=(s.top==0);
        return f;
    }
    boolean StackFull(StackType s)//判断栈是否为满
    {
        boolean f;
        f=(s.top==maxsize);
        return f;
    }
    void STClear(StackType s)//清空栈
    {
        s.top=0;
    }
    int PushSt(StackType s,DATA data)//入栈操作
    {
        if(s.top+1>maxsize)
        {
            System.out.println("栈以满");
            return 0;
        }
        s.data[++s.top]=data;
        //细节:先++再在加过后的top所指的地方按放数据。
        //本来top指的是3,3已经有数据了,就先将top上移然后在存放数据
        return 1;
    }
    DATA PopSt(StackType s)//出栈操作
    {
        if(s.top==0)
        {
            System.out.println("栈空");
           System.exit(0);//0表示正常退出,其他数字表示非正常退出
        }
        return (s.data[s.top--]);
        //细节:top本来指向3,先用3这个数字,先将3这块的数据输出来后再将top--
    }
    DATA PeekST(StackType s)//读栈顶元素
    {
        if(s.top==0)
        {
            System.out.println("栈空");
            System.exit(0);
        }
        return (s.data[s.top]);
        //不做++或--操作因为只读不取,由于栈特殊操作所以只能读栈顶元素
    }
}

接下来我们写一个Test类来测试一下我们写的栈

import java.util.Scanner;
public class Test {
    public static void main(String[] args)
    {
        StackType st=new StackType();
        Scanner in=new Scanner(System.in);
        DATA data1=new DATA();
        StackType stack=st.STInit();//初始化栈
        while(true)
        {
            System.out.println();
            System.out.println("输入1入栈");
            System.out.println("输入2出栈");
            System.out.println("输入3读取栈顶操作");
            System.out.println("输入4判断栈是否为空");
            System.out.println("输入5判断栈是否满");
            System.out.println("输入0退出");
            int n=in.nextInt();
            if(n==1)
            {
                DATA data=new DATA();
                
                    System.out.println("请输入姓名,年龄进行入栈操作");
                    data.name = in.next();
                            data.age=in.nextInt();
                            st.PushSt(stack,data);
            }
            if(n==2)
            {
                System.out.println("按任意非0键进行出栈操作");
               String temp=in.next();
               while(!temp.equals("0"))
               {
                   data1=st.PopSt(stack);
                   System.out.println("姓名 年龄");
                   System.out.printf("%s %d\n",data1.name,data1.age);
                   temp=in.next();
               }
            }
            if(n==3)//读取栈顶
            {
                data1=st.PeekST(stack);
                System.out.println("姓名 年龄");
                System.out.printf("%s %d\n",data1.name,data1.age);
            }
            if(n==4)//判断栈是否为空
            {
                boolean f=st.StackEmpty(stack);
                if(f)
                {
                    System.out.println("栈为空");
                }
                else
                    {
                        System.out.println("栈非空");
                    }
            }
            if(n==5)//判断栈是否满
            {
                boolean f=st.StackFull(stack);
                if(f)
                {
                    System.out.println("栈以满");
                }
                else
                {
                    System.out.println("栈非满");
                }
            }
            if(n==0)
            {
                System.out.println("谢谢使用");
                break;
            }
        }

    }
}

总结:以上就是一个栈的基本操作,我们用数组来作为承装数据的容器,我们一共建了三个类:
DATA 放数据的类
StackType 栈结构的类
Test 测试的类
欢迎各位来评论!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值