【数据结构】栈与实现分析

概念

 

(百度百科)栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

 

概念先不说,单从操作上来看, “链表”的所有操作完全包含了栈的操作。对我个人而言,不就换个包装吗。当然,这只是我对栈理解的第一印象而已。数据结构讲究的是搭配和组成的方法,是一个相对比较概念化的东西。既然栈可以作为基本数据结构之一,那肯定是栈的所有特性都是通过大量数据搭配和使用的一种抽象。说白了就是这样的搭配方式非常通用,否则“栈”也不会出现。从这个角度看,那么所谓的链表或数组都是实现栈这个数据搭配方法的工具和手段而已。那么下面再来学习一下栈到底有什么特性:

 

后进先出(Last In First Out,LIFO:从概念上可以知道,只允许在表的一端进行插入和删除操作,那好比如一个在商店里买的一桶羽毛球,只能在这个桶的一端打开口,每次拿出来的羽毛球都是接近口的那个,那也意味着接近口的那个羽毛球也是最后放进去的(不谈论厂家装货的一些特殊手段),这样比较好理解。

 

再来看看栈的一些基本操作:

1、构造空栈:InitStack(S)、

2、判栈空: StackEmpty(S)、

3、判栈满: StackFull(S)、

4、进栈: Push(S,x)、可形象地理解为压入,这时栈中会多一个元素

5、退栈: Pop(S) 、 可形象地理解为弹出,弹出后栈中就无此元素了。

6、取栈顶元素:StackTop(S),不同与弹出,只是使用栈顶元素的值,该元素仍在栈顶不会改变。

 

以上这些都是概念性的东西,要自己实现一个栈,那就得满足以上概念需求。下面结合Java语言中的Stack类的源码分析它是如何实现的。

 

实现分析

 

从Stack类的源码看,它本身是没有属性的,但它却继承了Vector类。而Vector是一个数组的实现,看看Vector的属性:

protected Object[] elementData; //数组元素
protected int elementCount; //数组的存放元素数量
protected int capacityIncrement; //数组可扩容的容量大小
private static final long serialVersionUID=…; //序列化版本标识

所以这个Stack类是基于数组实现的。也成为顺序栈,还有一种栈是基于链表结构实现的叫链栈。这两个种类栈的区别其实就是数组与链表特性的区别,例如数据有顺序的,但扩展没那么方便;而链表是没有顺序可言,不过扩展线性扩展相对方面。接下来看看这个Stack类的一下基本操作方法是怎样实现的:

/*元素入栈,通过在Vector数组中添加元素*/
public E push(E item) {
    addElement(item);
    return item;
}

/*元素出栈,通过在Vector数组中减少元素*/
public synchronized E pop() {
    E    obj;
    int    len = size();
    obj = peek();
    removeElementAt(len - 1);
    return obj;
}

/*判断栈是否为空*/
public boolean empty() {
    return size() == 0;
}

/*查找栈内元素*/
public synchronized int search(Object o) {
    int i = lastIndexOf(o);
    if (i >= 0) {
        return size() - i;
    }
    return -1;
}

通过对Stack的分析可以看出,栈的一些操作特点是非常依赖于对栈实现的工具,例如这个Vector类是个数组实现,那么这个栈的所有操作就是对数组的操作。

原文地址:https://www.cnblogs.com/wcd144140/p/5340206.html