zoukankan      html  css  js  c++  java
  • 数据结构笔记--栈的总结及java数组实现简单栈结构

    杂谈"栈"结构:  

      栈(Stack)是一种插入删除操作都只能在一个位置上进表,这个位置位于表的末端,叫做栈顶(Top).

      对栈的基本操作有push和pop,表示进栈和出栈.也就相当于插入和删除操作.

      栈结构又叫做LIFO(后进先出)表.归根结底是一个表结构,因此任何能够实现表结构的方法都能实现栈.

      在java语言中,ArrayList和LinkedList都支持栈操作,栈操作都是常数时间的操作,栈的实现方式一般有两种,一种是使用顺序存储的方式,即使用数组来实现,用ArrayList可以轻易实现栈结构,也可以自己使用数组来实现,一会下面我就用数组来实现栈,第二种是使用链式存储实现,即可以使用LinkedList来实现.

    使用数组实现顺序栈:

      使用arrayList和linkedList实现栈比较简单,毕竟本身他们就是封装好的功能,接下来我用数组来实现一个栈结构:

    MyStack:

    package com.wang.list;
    
    import java.util.Arrays;
    
    public class MyStack<T> {
    
        //使用数组实现这个栈结构
        private T[] dataArr;
        //当前元素的个数
        private int theSize;
        //栈的容量
        private static final int DEFAULT_CAPACITY=10;
        
        public MyStack(){
            clear();
            
        }
        //初始化数组,默认大小10,元素个数theSize初始化为o
        private void clear(){
            theSize=0;
            ensureCapacity(DEFAULT_CAPACITY);
        }
        
        //栈元素容量
        public int size(){
            return theSize;
        }
        
        private void ensureCapacity(int newCapacity){
            if(newCapacity<theSize){
                return;
            }
            T[] oldArr=dataArr;
            dataArr=(T[])new Object[newCapacity];
            for(int i=0;i<size();i++){
                dataArr[i]=oldArr[i];
            }
            
        }
        //入栈
        public void push(T value){
            if(dataArr.length==size()){
                ensureCapacity(size()*2);
            }
            dataArr[theSize++]=value;
        }
        //栈是否为空
        public boolean isEmpty(){
            return size()==0;
        }
        //出栈
        public T pop(){
            if(isEmpty()){
                return null;
            }
            T theValue=dataArr[theSize-1];
            dataArr[--theSize]=null;
            return theValue;
            
        }
        //返回栈尾元素
        public T peek(){
            if(isEmpty()){
                return null;
            }
            T theValue=dataArr[theSize-1];
            return theValue;
        } 
    }

    使用Node()辅助类实现链式栈:

    package com.wang.list;
    
    public class MyStack1<T> {
    
        
        private class Node{
            
             T data;
            Node next;
            
            
            public Node(T data,Node next){
                
                this.data=data;
                this.next=next;
            }
        }
        
        //保存元素个数
        private int theSize;
        
        //保存栈顶元素
        private Node top;
        
        public MyStack1(){
            top=null;
        }
        
        public MyStack1(T value){
            top=new Node(value,null);
        }
        
        public void push(T value){
            top=new Node(value,top);
            theSize++;
            
        }
        
        public T pop(){
            Node old=top;
            top=top.next;
            old.next=null;
            theSize--;
            return old.data;
            
        }
        
        public T peek(){
            return top.data;
            
        }
        public int size(){
            return theSize;
        }
        
        public boolean isEmpty(){
            return size()==0;
        }
    }

    栈的应用:

      进制转换:

        比如将十进制下的某个数转换为二进制中的某个数,则可以对该数进行除2取余操作,然后将余数压栈,之后再将所有的数出栈,即是所对应的二进制数,这其实是栈对于逆序操作的一个实例.

      平衡符号:

        检查那些成对出现的符号是否匹配,比如(),[],{}等

        实现过程大概如下:

          做一个空栈,读入字符直到文件末尾.如果字符是一个开放符号(比如"{}"中的"{"),则将其推入栈中.如果字符是一个封闭符号(比如"{}"中的"}"),则判断栈是否为空,为空则报错.不为空,则将栈顶元素弹出,判断弹出元素是否是其对应的开放符号,不是则报错,在文件结尾,如果栈非空,就报错.

      后缀表达式:

        不知道何为后缀表达式,请自行百度,后缀表达式的记法又称为逆波兰式,它的求值过程恰好就是从左到右的过程,可以使用一个栈,当见到一个数时就入栈,当遇到一个一个运算符时,就从栈中弹出两个数进行计算,再将所得结果入栈.最后的到的数就是计算结果.

      用于方法调用:

        存在方法调用时,比如在一个方法中调用了另一个方法,这时候需要把当前方法一些重要信息记录并保存下来,保存到一个栈中,然后再跳到新方法中去执行,当方法返回的时候,去查看栈顶的那个保存信息(栈帧),然后进行复原,事实上这是在计算机系统中一个非常重要的应用,上面的全部工作都可以用一个栈来实现.事实上,在实现递归的每一种程序语言都是这么干的,所存储的信息叫做活动记录,或者说栈帧.这个细说,比较复杂,想深入了解,自己百度吧.

  • 相关阅读:
    C语言II博客作业01
    vscode使用相关配置
    Ubuntu配置教程
    编译原理复习
    误差与过拟合
    机器学习分类
    SQL语句使用详解
    CRC模2除法
    数据链路层之差错控制(检错编码和纠错编码)->(奇偶校验码、CRC循环冗余码、海明码)
    封装成帧、帧定界、帧同步、透明传输(字符计数法、字符串的首尾填充法、零比特填充的首尾标志法、违规编码法)
  • 原文地址:https://www.cnblogs.com/fingerboy/p/5479525.html
Copyright © 2011-2022 走看看