数据结构之栈

原创 2018年04月16日 17:14:11

一、Stack源码分析
1.继承结构
 栈是数据结构中一种很重要的数据结构类型,因为栈的后进先出功能是实际的开发中有很多的应用场景。Java API中提供了栈(Stacck)的实现。
Stack类继承了Vector类,而Vector类继承了AbstractList抽象类,实现了List接口,Cloneable接口,RandomAcces接口以及Serializable接口,需要指出的Vector内部还有两个内部类ListItr和Itr,Itr在继承Vector的同时实现了Iterator接口,而ListItr在继承了Itr类的同时实现了ListIterator接口。
图解

源码分析
Stack类里的方法:
1).public Stack() //一个无参构造方法,能直接创建一个Stack
2).public E push(E item) //向栈顶压入一个项
3).public synchronized E pop() //移走栈顶对象,将该对象作为函数值返回
4).public synchronized E peek() //查找栈顶对象,而不从栈中移走。
5).public boolean empty() //测试栈是否为空
6).public synchronized int search(Object o) //返回栈中对象的位置,从1开始。
private static final long serialVersionUID = 1224463164541339165L;

其他值的方法是从Vector类继承而来,通过源码可以发现Vector有几个属性值:
protected Object[] elementData //elementData用于保存Stack中的每个元素;
protected int elementCount //elementCount用于动态的保存元素的个数,即实际元素个数
protected int capacityIncrement //capacityIncrement用来保存Stack的容量(一般情况下应该是大于elementCount)
private static final int MAX_ARRAY_SIZE = 2147483639 ; //MAX_ARRAY_SIZE 用于限制Stack能够保存的最大值数量

    //向栈顶压入一个项
    public E push(E item) {
    //调用Vector类里的添加元素的方法
        addElement(item);

        return item;
    }

    public synchronized void addElement(E obj) {
    //通过记录modCount参数来实现Fail-Fast机制
        modCount++;
    //确保栈的容量大小不会使新增的数据溢出
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = obj;
    }

    private void ensureCapacityHelper(int minCapacity) {
        //防止溢出。超出了数组可容纳的长度,需要进行动态扩展!!!  
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    //数组动态增加的关键所在
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
    //如果是Stack的话,数组扩展为原来的两倍
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);

    //扩展数组后需要判断两次
    //第1次是新数组的容量是否比elementCount + 1的小(minCapacity;)
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;

    //第1次是新数组的容量是否比指定最大限制Integer.MAX_VALUE - 8 大
    //如果大,则minCapacity过大,需要判断下
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    //检查容量的int值是不是已经溢出 
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
//查找栈顶对象,而不从栈中移走。
public synchronized E peek() {
    int len = size();

    if (len == 0)
        throw new EmptyStackException();
    return elementAt(len - 1);
}

//Vector里的方法,获取实际栈里的元素个数
public synchronized int size() {
    return elementCount;
}

public synchronized E elementAt(int index) {
    if (index >= elementCount) {
    //数组下标越界异常
        throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
    }

//返回数据下标为index的值
    return elementData(index);
}

@SuppressWarnings("unchecked")
E elementData(int index) {
    return (E) elementData[index];
}
//移走栈顶对象,将该对象作为函数值返回
public synchronized E pop() {
    E obj;
    int len = size();

    obj = peek();
//len-1的得到值就是数组最后一个数的下标
    removeElementAt(len - 1);

    return obj;
}

//Vector里的方法
public synchronized void removeElementAt(int index) {
    modCount++;
//数组下标越界异常出现的情况
    if (index >= elementCount) {
        throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
    } else if (index < 0) {
        throw new ArrayIndexOutOfBoundsException(index);
    }

 //数组中index以后的元素个数,由于Stack调用的该方法,j始终为0
    int j = elementCount - index - 1;
    if (j > 0) {
    // 数组中index以后的元素,整体前移,(这个方法挺有用的!!)  
        System.arraycopy(elementData, index + 1, elementData, index, j);
    }
    elementCount--;
    elementData[elementCount] = null; /* to let gc do its work */
}
// 返回栈中对象的位置,从1开始。如果对象o作为项在栈中存在,方法返回离栈顶最近的距离。
//栈中最顶部的项被认为距离为1。
public synchronized int search(Object o) {
//lastIndexOf返回一个指定的字符串值最后出现的位置,
//在一个字符串中的指定位置从后向前搜索
    int i = lastIndexOf(o);

    if (i >= 0) {
    //所以离栈顶最近的距离需要相减
        return size() - i;
    }
    return -1;
}

//Vector里的方法
public synchronized int lastIndexOf(Object o) {
    return lastIndexOf(o, elementCount-1);
}

public synchronized int lastIndexOf(Object o, int index) {
    if (index >= elementCount)
        throw new IndexOutOfBoundsException(index + " >= "+ elementCount);

//Vector、Stack里可以放null数据
    if (o == null) {
        for (int i = index; i >= 0; i--)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = index; i >= 0; i--)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/KSMaster/article/details/79963360

数据结构学习之路-第三章:栈的应用

【 声明:版权所有,转载请标明出处,请勿用于商业用途。  联系信箱:libin493073668@sina.com】 前言: 前面已经介绍过栈的相关操作的具体实现,那么现在就按...
  • libin1105
  • libin1105
  • 2015-09-08 19:15:33
  • 1677

数据结构(5)--栈的定义以及相关操作的实现

 参考书籍:数据结构(C语言版) 严蔚敏 吴伟民编著 清华大学出版社 1.栈的定义     栈(stack)是限定在表尾一端进行插入或删除操作的线性表。在栈中,允许插入和删除操作的一端称为栈...
  • u010366748
  • u010366748
  • 2016-02-05 22:26:07
  • 2639

数据结构栈的运算

栈在表达式过程中的应用:建立操作数栈和运算符栈。运算符有优先级。规则: 自左至右扫描表达式,凡是遇到操作数一律进操作数栈。 当遇到运算符时,如果它的优先级比运算符栈栈顶元素的优先级高就进栈。反之,...
  • Allureyou
  • Allureyou
  • 2016-11-07 21:10:23
  • 605

C语言实现数据结构中的链栈

实现方式一# include # include typedef char NodeData;//链栈typedef struct Node{ NodeData data; struct Node *...
  • fullbug
  • fullbug
  • 2007-04-22 16:11:00
  • 5178

数据结构之 栈(C语言实现)

数据结构之 栈(C语言实现)1.栈的模型栈(stack)是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈的顶(top)。对栈的基本操作有push(进栈)和pop(出栈),前者相当于插...
  • men_wen
  • men_wen
  • 2017-03-14 23:23:20
  • 1035

[数据结构]栈的基本操作

栈的基本操作
  • napoay
  • napoay
  • 2015-11-23 08:42:56
  • 3539

常见数据结构(一)-栈,队列,堆,哈希表

本文介绍几种常见的数据结构:栈、队列、堆、哈希表,等等。
  • h3243212
  • h3243212
  • 2016-10-14 00:35:03
  • 5092

数据结构-栈和队列小结

1栈   1>栈的定义:       栈是限定仅在表尾进行插入和删除操作的线性表。       我们把插入和删除的一端称为栈顶(TOP),另一端称为栈底(BOTTOM),不包含任何元素的栈称为空...
  • XiangTianZaiJie500
  • XiangTianZaiJie500
  • 2016-10-24 17:22:22
  • 2082

[数据结构与算法分析]栈的应用-学习笔记

平时我们很少接触到一个栈的使用,但是今天看了如下三个例子后感触颇深,对于栈应用的情况理解更深了。分享如下: 1、平衡符号 平衡是个动词,意思就是用来平衡符号的,例如关于方法里{}左右大括号的匹配问...
  • u014629433
  • u014629433
  • 2016-06-06 09:04:48
  • 812

数据结构中的栈与汇编语言中的栈的区别

在《数据结构》中,我们知道有关于栈的概念都是逻辑上的,而在《汇编语言》一门课中,关于栈的操作就是对内存的操作。以下的都是我在学习了王爽的《汇编语言》第三版以及清华大学出版社的《数据结构》第四版的有关栈...
  • ZLJmooli
  • ZLJmooli
  • 2016-12-29 11:46:49
  • 707
收藏助手
不良信息举报
您举报文章:数据结构之栈
举报原因:
原因补充:

(最多只允许输入30个字)