• 3.1_栈_顺序存储结构(数组形式)


    【栈的定义】

    栈(stack)是限定仅在表尾进行插入和删除操作的线性表。

    栈又称为后进先出(Last In First Out)线性表,简称LIFO结构。

    (PS:定义中的表尾是指 栈顶!)

    【几个关键词 】

    [ 栈顶(top) ]

    允许插入和删除的一端称为 栈顶。

    [ 栈底(bottom) ]

    栈顶的另一端称为 栈底。

    [ 空栈 ]

    不含任何数据元素的栈。

    【栈的插入操作——进栈(push)】

      栈的插入操作,叫做进栈,也称为压栈、入栈。

    【栈的删除操作——出栈(pop)】

      栈的删除操作,叫做出栈,也称为弹栈。

           

    【进栈出栈的变化形式】

    如果3个整数1,2,3依次入栈,会有哪些出栈次序?

    第一种:1-2-3进栈,即3-2-1出栈。

    第二种:1进,1出,2斤,2出,3进,3出,进一个出一个,即1-2-3出栈。

    第三种:1进,2进,2出,1出,3进,3出,即2-1-3出栈。

    第四种:1进,1出,2进,3进,3出,2出,即1-3-2出栈。

    第四种:1进,2进,2出,3进,3出,2出,即2-3-1出栈

    【栈的抽象数据类型】

    ADT 栈(stack)
    Data
        同线性表。元素具有相同的类型,相邻元素具有前驱和后继关系。
    Operation
        InitStack(*S)    初始化操作,建立一个空栈S
        DestoryStack(*S) 若栈存在,则销毁它
        ClearStack(*S)   将栈清空
        StackEmpty(S)    若栈为空,返回true,否则返回false。
        GetTop(S,*e)     若栈S存在且非空,用e返回S的栈顶元素。
        Push(*S,e)       若栈S存在,插入新元素e到栈S中并成为栈顶元素。
        Pop(*S,*e)       删除栈S中栈顶元素,并用e返回其值。
        StackLength(S)   返回栈S的元素个数。
    endADT

    【自定义的栈MyStack.java】

    package com.Higgin.Stack;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.EmptyStackException;
    
    public class MyStack {
        protected Object[] elementData; //栈中具体的对象数组
        protected int elementCount;     //栈顶指针
        protected int capacityIncrement;//当栈满了,每次增长栈的容量 
        
        public MyStack(int initialCapacity,int capacityIncrement){
            if(initialCapacity<0){   //如果初始化栈的容量小于0,抛出异常
                throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
            }
            this.elementData=new Object[initialCapacity];
            this.capacityIncrement=capacityIncrement;
        }
        
        public MyStack(int initialCapacity){
            this(initialCapacity,0);  //默认增长的容量为0
        }
        
        public MyStack(){
            this(10); //默认初始栈的容量为10
        }
        
        /**
         * 返回栈中的已存的元素个数
         */
        public int size(){
            return elementCount;
        }
        
        /**
         *  判断是否为空栈
         */
        public boolean empty(){
            return size()==0;
        }
        
        /**
         * 进栈
         */
        public Object push(Object obj){
            if((elementCount+1)>elementData.length){  //如果再添加一个对象,导致溢出,则扩容(若不想扩容直接抛出异常即可)
                grow(elementCount+1); //扩容
            }
            elementData[elementCount++]=obj;
            return obj;
        }
        
        /**
         * 查看栈顶部的元素,但不从栈中移除它
         */
        public Object peek(){
            int len=size();
            if(len==0){
                throw new EmptyStackException();
            }
            return elementData[len-1];
        }
        
        /**
         * 出栈
         */
        public Object pop(){
            Object obj=peek();  //获取栈顶的对象,里面包含了判断栈是否为空的判断
            elementCount--;
            elementData[elementCount]=null;
            return obj;
        }
        
        /**
         * 查找对象的位置
         */
        public int search(Object obj){
            if(size()==0){   //如果是空栈,直接不找
                throw new EmptyStackException();
            }
            int i=lastIndexOf(obj);
            if(i>=0){
                return size()-i;
            }
            return -1;
        }
        
        /**
         *  扩容
         * (如果再存入数据时,容量不够,就进行扩容)
         */
        public void grow(int minCapacity){   //扩容方法
            int oldCapacity=elementData.length;   //原来的容量
            int newCapacity=oldCapacity+((capacityIncrement>0)?capacityIncrement:oldCapacity);   //增长后的新容量:设置过就为 老容量+设置值 ,否则就直接翻倍 
            if(newCapacity<minCapacity){   //如果新增后的容量依然过小,直接把当前值指针的值传过来(这个应该是容量过大的时候)
                newCapacity=minCapacity;
            }
            if(newCapacity-Integer.MAX_VALUE>8){   
                if(minCapacity<0){  //说明都溢出了
                    throw new OutOfMemoryError();   //直接抛出错误
                }
                newCapacity=(minCapacity>(Integer.MAX_VALUE-8)?Integer.MAX_VALUE:(Integer.MAX_VALUE-8));
            }
            elementData=Arrays.copyOf(elementData, newCapacity);  //扩容后的elementData
        }
        
        /**
         * 找出obj对象在 elementData[i]中最后的位置,对于栈而言,其实是离栈顶最近的位置
         */
        public int lastIndexOf(Object obj){
            if(obj==null){
                for(int i=elementCount-1;i>=0;i--){
                    if(elementData[i]==null){
                        return i;
                    }
                }
            }else{
                for(int i=elementCount-1;i>=0;i--){
                    if(obj.equals(elementData[i])){
                        return i;
                    }
                }
            }
            return -1;
        }
    }

    【测试】

    package com.Higgin.Stack;
    
    import org.junit.Test;
    
    public class TestMyStack {
        @Test
        public void test1(){
            MyStack ms=new MyStack();
            System.out.println("是否为空==="+ms.empty());                  //true
            ms.push(11);
            ms.push(22);
            ms.push(33);
            System.out.println("最近一次添加的是33==="+ms.peek());          //33
            ms.push(44); 
            ms.push(55);
            System.out.println("最近一次添加的是55==="+ms.peek());          //55
            System.out.println("寻找22的位置==="+ms.search(22));           //4
            System.out.println("寻找55的位置==="+ms.search(55));           //1
            System.out.println("寻找99的位置(不存在)==="+ms.search(99));    //-1
            ms.pop(); 
            System.out.println("执行了一次pop,栈顶的元素==="+ms.peek());    //44
            System.out.println("栈移除了之后的长度为===="+ms.size());        //4
            
        }
    }

    【运行结果】

  • 相关阅读:
    第二章 图像的显示
    c++ 使用PI
    c++函数写的都对,还是说incompatible或者not found的解决办法
    我理解的直方图均衡化
    解决360WiFi有时候手机连接不上
    c# 16进制byte转成int
    VS2010 代码突然改变字体 解决办法
    荣耀手机恢复那些“不再提示”的设置
    mfc视类中错误:IntelliSense: declaration is incompatible with。。。解决方案
    [原] Android 自定义View步骤
  • 原文地址:https://www.cnblogs.com/HigginCui/p/6095247.html
Copyright © 2020-2023  润新知