数据结构与算法之栈【三】

326 阅读3分钟

数组,链表,树等数据结构适用于存储数据库应用中的数据记录,他们常常用于记录那些对象以及数据,方便于数据的访问,插入,删除和查找特定的数据项

而栈和队列更多的是作为程序员的工具使用,这些数据的存储结构的生命周期比数据库类型的结构短很多在程序操作执行期间他们才被创建,通常他们是去执行特定的任务,任务完成后就销毁了

栈的主要功能可以用数组实现,也可以用链表实现

优先级队列的实现可以用数组或者一种特别的树,堆来实现

栈每次只允许访问一个数据项,即最后插入的数据,移除这个项才能访问倒数第二个插入的数据,它是一种后进先出的数据结构

栈的基本操作有:入栈(push),出栈(pop),查看栈顶元素,判断栈是否为空,判断栈是否饱和,读取栈的大小。

示例:使用数组实现一个栈

    public class Stack{
        private int size; //栈的大小
        private int top; //栈顶元素的角标
        private int[] stackArray; //栈的容器
        
        //构造方法
        public Stack(int size){
            stackArray = new int[size];
            top=-1; //初始化栈的时候,栈内无元素,栈顶下标为-1
            this.size=size;
        }
        
        //入栈,同时栈顶角标元素加1
        public void push(int element){
            stackArray[top++]=element;
        }
        //出栈,删除栈顶元素,同时栈顶元素的角标减1
        public int pop(){
            return stackArray[top--];
        }
        //查看栈顶元素,但是不删除
        public int peek(){
            return stackArray[top];
        }
        //判断栈是否为空
        public boolean isEmpty(){
            return (top == -1)
        }
        //判断栈是否满
        public boolean isFull(){
            return (top == size-1)
        }
    }

上面代码缺陷是不具备健壮性,还需要对可能的异常进行处理,比如在入栈之前, 要检查栈没有满,出栈之前要检查栈不为空。

栈通常用于解析某种类型的文本串,通常,文本串是计算机语言写的代码行,而解析他们的程序就叫做编译器。

下面使用栈实现一个案例:分隔符匹配。例如在eclipse中编程时,如果代码zho多写或者少写了一个{},都会报错,接下来用栈模拟分隔符匹配

分隔符程序从字符串中不断读取字符,每次读到一个字符,如果他是 {,(,[,那么就压入栈中,如果是 },),],那么就依次弹栈,如果左右分隔符匹配,不报错,不匹配,或者最后存在没有被匹配的分隔符,也报错。

例如: {([1])},这个字符串在栈中的变化过程

        所读字符                    栈中内容
            {                           {
            (                           {(
            [                           {([
            1                           {([
            ]                           {(
            )                           {   
            }                           空

由于匹配分隔字符串操作的是字符,所以只需要把上面的Stack的容器数组改为char类型的就可以了。

然后写一个类封装分隔符匹配的操作:

    public class BrecketChecker{
        private String input;//存储待检测的字符串
        //构造方法,接收检查的字符串
        public BrecketChecker(String input){
            this.input=input
        }
        
        //检测匹配字符串的方法
        public void check(){
            Stack stack = new Stack)(input.length);
            for(int i=0;i<input.length;i++){
                char ch = input.charAt(i);//每次获取字符串中的单个字符
                switch(ch){
                    case '{':
                    case '(':
                    case '[':
                        //如果为左分隔符就压入栈中
                        stack.push(ch);
                        break;
                    case ']':
                    case ')':
                    case '}':
                        //如果为右分隔符,弹栈,做匹配校验
                        if(!stack.isEmpty()){
                            char chx = stack.pop();
                            if(ch=='{'&&chx!='}' || ch=='('&& chx!=')' ||
                                ch =='['&& ch!=']'){
                                System.out.print('匹配字符串出错');
                            }
                        }else{
                            //如果没有左括号,直接来右括号,也报错。
                            System.out.println("匹配字符串出错");
                        }else{
                            System.out.println(“字符”+i+"匹配成功");
                        }
                    default:
                        break;
                }
            }
            if(!stack.isEmpty()){
                    System.out.print("有括号没有关闭");
            }
        }
    }