关于栈的简单理解

1. 栈(Stack)

1.1 文字讲解

        栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则(竖立的水杯模型)。其中一下两个操作是栈的主要操作:

        压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

        出栈:栈的删除操作叫做出栈。出数据在栈顶。

1.2 图像分析

        从上图中可以看到,Stack继承了Vector父类,Vector和ArrayList类似,都是动态的顺序表,不同的是Vector是线程安全的。 

        下图图一和图二分别是入栈和出栈操作关于栈顶和栈底的图解:

2、自定义栈的实现 

2.1  栈的实现方法和功能表达

        详细方法和功能如下图:

2.2 自定义栈的代码实现

        说明:本栈的实现主要 采用int型数组的结构;

2.2.1 栈的创建

        思路:

        1、创建一个MyStack类,其中定义两个成员变量,数组(用来存放底层数据)和长度(用来记录当前的栈里面存放数据的数量),实现3中定义的接口,重写其方法让栈的操作具体化;

        2、构造方法,创建一个默认长度为10的数组;

public class MyStack implements IStack{
    private int[] data;
    private int usedLength;//实际已经占用的数组长度

    private static final int Default_Length = 10;

    public MyStack() {
        this.data = new int[Default_Length];
    }


    @Override
    public void push(int x) {

    }

    @Override
    public int pop() {
        return 0;
    }

    @Override
    public int peek() {
        return 0;
    }

    @Override
    public int size() {
        return 0;
    }

    @Override
    public boolean empty() {
        return false;
    }

    @Override
    public boolean full() {
        return false;
    }
}

        3、定义一个接口,在里面创建栈一系列操作的抽象方法;

public interface IStack {
    void push(int x);
    int pop();
    int peek();
    int size();
    boolean empty();
    boolean full();
}

2.2.2 压栈方法的实现

        1、首先对当前栈进行判断是否为满,若满则需要对当前栈进行二倍容量扩容

        2、当栈的容量充足时,在栈顶进行入栈(底层数组尾部进行添加数据)

        3、当前栈的数量长度加一;

@Override
    public void push(int x) {
        if (full() == true){
            this.data = Arrays.copyOf(data,2*Default_Length);
        }
        data[usedLength] = x;
        usedLength++;
    }

    @Override
    public boolean full() {
        if (usedLength == data.length){
            return true;
        }
        return false;
    }

 2.2.3 栈是否为空操作

 @Override
    public boolean empty() {
        return usedLength == 0;
    }

2.2.4出栈的实现

       思路:

         1、首先得判断当前栈栈是否为空,若为空我们需要抛出栈为空自定义异常(自定义一个异常为EmptyException);

public class EmptyException extends RuntimeException{
    public EmptyException(String msg) {
        super(msg);
    }
}

        2、将当前的栈顶的元素存储到容器中并返回

        3、将栈的长度加一,之前栈顶的数据引用地址就会变成null(空指针),出栈的数据的地址就不会被引用而导致数据从栈里消失;

        图解如下:

        代码如下:

 @Override
    public int pop() {
       if (empty()){
           throw new EmptyException("当前这个栈是空的!!!");
       }
 
        int old = data[usedLength-1];
        usedLength--;//相当于是删除
        return old;
    }

2.2.5获取栈中数据元素个数

@Override
    public int size() {
        return usedLength;
    }

2.2.6获取栈顶元素

        思路类似于2.2.4;

 @Override
    public int pop() {
       if (empty()){
           throw new EmptyException("当前这个栈是空的!!!");
       }
        int old = data[usedLength-1];
        usedLength--;//相当于是删除
        return old;
    }

3.关于链表的栈使用
3.1单链表

        从头部插入(入栈),从头部删除(出栈),时间复杂度为O(1);

         从尾部插入(入栈),从尾部删除(出栈),时间复杂度为O(n);不建议使用

3.2双向链表:

        从头部插入(入栈),从头部删除(出栈)

        从尾部插入(入栈),从尾部删除(出栈),有last引用,直接到表尾部        

        二者时间复杂度皆为O(1);

3.3 LinkedList自带实现方法:

 public static void main(String[] args) {
        LinkedList<Integer> linkedList = new LinkedList<>();
        linkedList.push(101);
        linkedList.push(102);
        linkedList.push(103);
        linkedList.push(104);
        System.out.println(linkedList.peek());
        System.out.println(linkedList.pop());
        System.out.println(linkedList.pop());
    }

        测试结果:

 

4.Q&A

Q1:栈、虚拟机栈、栈帧有什么区别呢?

A1:

        栈:是一种数据结构里面的概念,用来存放数据的一种模式;

        虚拟机栈:jvm虚拟机划分的一块内存;

        栈帧:调用方法的时候会在虚拟机中给这个方法开辟一个空间;

ps:本次内容就到这里了,如果喜欢的话就请一键三连哦!!!


 

  • 33
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值