3.1_栈和队列_栈

Posted HigginCui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
        
    }
}

【运行结果】

 

以上是关于3.1_栈和队列_栈的主要内容,如果未能解决你的问题,请参考以下文章

python的栈和队列的实现代码

python的栈和队列的实现代码

Python实现栈和队列

python实现栈和队列

栈和队列

python两个队列实现一个栈和两个栈实现一个队列