数据结构----栈的详解

栈的定义

栈是只允许许一段进行插入或删除操作的线性表。首先栈是一种线性表,但限定这种线性表只能在某一段进行插入和删除操作,如下图所示

  • 栈顶:线性表允许进入插入删除的那一端
  • 栈底:固定的,不允许进行插入和删除的另一端
  • 空栈:不含任何元素的空表

栈是一种受限的线性表,类似线性表,他也有对应的两种存储方式

栈分为顺序栈,共享栈,链栈

顺序栈的基本操作

初始化一个栈



public class MyStack {
    private int[] stack;//存放数据
    private int top;//栈顶指针
    private int maxSize;//数组元素最大个数
    public MyStack(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[maxSize];
        top = -1;//栈顶指针初始化为-1
    }
}

栈中没有元素时,栈顶指针默认是-1

用构造方法指定栈的容量

判断栈为空

 public boolean isEmpty(){
        return top==-1;
    }

仅仅需要判断top指针

出栈

 //出栈操作
    public int pop(){
        if(top==-1){
            System.out.println("栈空");
            return -1;
        }else{
            int data = stack[top];
            top--;
            return data;
        }
    }

进栈

//入栈操作
    public void push(int data){
        if(top==maxSize-1){
            System.out.println("栈满");
        }else{
            top++;
            stack[top]=data;
        }
    }

读取栈顶元素

 public Integer readTop(){
        if(top==-1){
            System.out.println("栈空");
            return null;
        }else{
            return stack[top];
        }
    }

为什么用Integer类型?而不用int,原因是int类型返回值不能为空,而包装类Integer可以

输出栈中元素

 //输出栈中元素
    public void printStack(){
        for(int i=top;i>=0;i--){
            System.out.println(stack[i]);
        }
    }

共享栈定义

利用栈底卫生纸相对不变的特性,可让两个是顺序栈共享一个一维数组空间,将两个栈的栈底分别设置在共享空间的两端,两个栈顶想共享空间的中间延伸,如下如所示

两个栈的栈顶指针都指向栈顶元素,top0=-1时0号栈为空,top1=Maxsize时1号栈为空;仅当两个栈顶指针相邻(top1-top0=1)时,判断为栈满。当0号栈进栈时 top0 先加 1再赋值,1号栈进栈时top1先减1再赋值;出栈时则刚好相反。
共享栈是为了更有效地利用存储空间,两个栈的空间相互调节,只有在整个存储空间被占满时才发生上溢。其存取数据的时间复杂度均为O(1),所以对存取效率没有什么影响。

栈的链式存储

采用链式存储的栈称为链栈,链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。通常采用单链表实现,并规定所有操作都是在单链表的表头进行的。值为a1的节点为栈顶节点

链栈的基本操作单链表的基本操作基本大同小异,这里就不过多介绍了

下面我们介绍一下Java自己的栈

首先需要导包 util包下的Stack,下图是相应的方法

  • empty(): 这个方法通常用于检查栈是否为空。
  • peek(): 返回栈顶的元素但不移除它。
  • pop(): 移除并返回栈顶的元素。
  • push(element): 将指定的元素压入栈顶。
  • search(element): 在栈中搜索指定的元素并返回其位置,其中最顶部的元素位置为1。

我们可以看到,Stack继承Vector Vector相信大家不陌生,也是一个动态数组,和ArrayList有点相似,不过Vector是线程安全的

下面我们来详解一下Stack进栈的过程

//下面的代码为Stcak进栈的方法,可以看到,它调用了vector的addElement方法
 public E push(E item) {
        addElement(item);

        return item;
    }
//我们接着点进去看看

public synchronized void addElement(E obj) {
        modCount++;
        add(obj, elementData, elementCount);
    }
//首先我们看modCount,这个属性并不是vector类的,而是vector父类AbstractList<>类中的属性,此字段由 iterator 和 listIterator 方法返回的 iterator 和 list iterator 实现使用。如果此字段的值意外更改,则迭代器(或列表迭代器)将抛出 ConcurrentModificationException 以响应 next、remove、previous、set 或 add 操作。

//接着我们看add方法  此方法是本类的
//此方法就是将e添加到elementData数组中s的位置,很好理解
 private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)
            //如果数组满了就对其扩容
            elementData = grow();
        elementData[s] = e;
        elementCount = s + 1;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值