Java的顺序栈和链式栈

栈的定义

栈是限制在表的一段进行插入和删除的运算的线性表,通常能够将插入、删除的一端为栈顶,例外一端称为栈底,当表中没有任何元素的时候称为空栈。

通常删除(又称“退栈”)叫做弹出pop操作,每次删除的都是栈顶最新的元素;每次插入(又称“进栈”)称为压入push操作。

当栈满的时候,进行push 操作,会上溢,当空栈的时候进行退栈操作的时称为下溢

上溢是一种出错的情况,下溢可能是正常的情况处理。

堆栈的运算是按照后进先出的原则,简称LIFO

栈的基本运算定义:

  • initStack:构造一个空栈;
  • stackEmpty:判断是否为空;
  • stackFUll:判断是否栈满;
  • push:进栈,将该元素压入栈顶;
  • pop:退栈,弹出栈顶元素,注意非空判断;
  • stackTop:去除栈顶元素,不改变指针。

做个简单的Stack接口:

package com.wuwii.utils;

/**
 * 堆栈
 * @author Zhang Kai
 * @version 1.0
 * @since <pre>2017/12/14 22:51</pre>
 */
public interface Stack<E> {
    /**
     * 进栈
     *
     * @param element 进栈的元素
     */
    void push(E element);

    /**
     * 弹出栈顶元素 ,并改变指针
     *
     * @return 栈顶元素
     */
    E pop();

    /**
     * 返回栈顶元素 ,不改变指针
     *
     * @return 栈顶元素
     */
    E topElement();

    /**
     * 判断是否为空栈
     *
     * @return true为空栈
     */
    Boolean isEmpty();

    /**
     * 清空栈
     */
    void clear();

}

顺序栈

就是符合LIFO运算规则的顺序线性表。

package com.wuwii.utils;

/**
 * 顺序栈
 * @author Zhang Kai
 * @version 1.0
 * @since <pre>2017/12/14 23:05</pre>
 */
public class ArrayStack<E> implements Stack<E> {
    /**
     * 初始化栈的默认大小
     */
    private final int defaultSize = 10;
    /**
     * 栈的集合大小
     */
    private int size;
    /**
     * 栈顶的位置
     */
    private int top;
    /**
     * 元素存储在数组
     */
    private Object[] elements;

    /**
     * 初始化默认大小为10 的栈
     */
    public ArrayStack() {
        initStack(defaultSize);
    }

    /**
     * 初始化指定大小的栈
     * @param givenSize 指定栈大小
     */
    public ArrayStack(Integer givenSize) {
        initStack(givenSize);
    }

    /**
     * 初始化栈
     * @param givenSize 给定的栈大小
     */
    private void initStack(Integer givenSize) {
        size = givenSize;
        top = 0;
        elements = new Object[size];
    }

    /**
     * 清空栈
     */
    @Override
    public void clear() {
        top = 0;
    }

    /**
     * 进栈
     * @param element 进栈的元素
     */
    @Override
    public void push(E element) {
        sizeCheckForPush();
        elements[top++] = element;
    }

    /**
     * 弹出栈顶元素 ,并改变指针
     * @return 栈顶元素
     */
    @Override
    public E pop() {
        sizeCheckForPop();
        return (E) elements[--top];
    }
    /**
     * 返回栈顶元素 ,不改变指针
     * @return 栈顶元素
     */
    @Override
    public E topElement() {
        sizeCheckForPush();
        return (E) elements[top - 1];
    }

    /**
     * 判断是否为空栈
     * @return true为空栈
     */
    @Override
    public Boolean isEmpty() {
        return size == 0;
    }

    /**
     * 在进栈的时候检查
     */
    private void sizeCheckForPush() {
        if (top >= size) {
            throw new RuntimeException("Stack overflow");
        }
    }

    /**
     * 退栈检查
     */
    private void sizeCheckForPop() {
        if (isEmpty()) {
            throw new RuntimeException("Stack is empty");
        }
    }
}

链式栈

符合LIFO运算规则的链式线性表。

package com.wuwii.utils;

/**
 * @author Zhang Kai
 * @version 1.0
 * @since <pre>2017/12/15 12:58</pre>
 */
public class LinkStack<E> implements Stack<E> {
    /**
     * 链式单元
     */
    private Node<E> top;

    /**
     * 初始化链式堆栈
     */
    public LinkStack() {
        initStack();
    }

    /**
     * 初始化
     */
    private void initStack() {
        top = null;
    }

    /**
     * 存储单元
     */
    private static class Node<E> {
        E element;
        Node<E> next;
        Node(E element, Node<E> next) {
            this.element = element;
            this.next = next;
        }
    }
    /**
     * 进栈
     *
     * @param element 进栈的元素
     */
    @Override
    public void push(E element) {
        top = new Node<E>(element, top);
    }

    /**
     * 弹出栈顶元素 ,并改变指针
     *
     * @return 栈顶元素
     */
    @Override
    public E pop() {
        checkEmpty();
        E element = top.element;
        top = top.next;
        return element;
    }

    /**
     * 返回栈顶元素 ,不改变指针
     *
     * @return 栈顶元素
     */
    @Override
    public E topElement() {
        checkEmpty();
        return top.element;
    }

    /**
     * 判断是否为空栈
     *
     * @return true为空栈
     */
    @Override
    public Boolean isEmpty() {
        return top == null;
    }

    /**
     * 清空栈
     */
    @Override
    public void clear() {
        if (isEmpty()) {
            return;
        }
        for (Node<E> x = top; x != null; ) {
            Node<E> next = x.next;
            x.element = null;
            x.next = null;
            x = next;
        }
        size = 0;
    }

    /**
     * 检查链式堆栈是否为空,为空抛出异常
     */
    private void checkEmpty() {
        if (isEmpty()) {
            throw new RuntimeException("LinkStack is empty");
        }
    }
}

首先push 修改新产生的链表节点的next 域并指向栈顶,然后设置top 指向新的链表节点,pop则相反。

顺序栈和链式栈的比较

实现链式栈和顺序栈的操作都是需要常数时间,时间复杂度为O(1),主要从空间和时间复杂度考虑。

顺序栈初始化的时候必须要给定指定大小,当堆栈不满的时候,会造成一部分的空间浪费,链式栈变长,相对节约空间,但是增加了指针域,额外加大了数据结构的开销。

当需要多个堆栈共享的时候,顺序存储中可以充分的利用顺序栈的单向延伸,将一个数组可以存在两个堆栈里,每个堆栈从各自的栈顶出发延伸,这样减少了空间的浪费。但只有两个为堆栈的空间有相反的需求的时候才能使用。就是最好一个堆栈只能增加,一个只能减少。如果,两个一起增加,可能造成堆栈的溢出。

如果在多个顺序堆栈共享空间,一个堆栈满了,其他可能没满,需要使用堆栈的LIFO 运算法则,将满的堆栈元素向左或者右进行平移操作,这样会造成大量的数据元素移动,使得时间的开销增大。

相对来说,使用两个堆栈共享一个空间是比较适宜的存储方式,但是也增加了堆栈溢出的危险。

由于链式存储结构的不连续性,什么时候需要,就什么时候去存储,不存在溢出的问题,但是增加了结构的开销,总体上来说浪费了空间,但是不需要堆栈共享,

原文地址:https://www.cnblogs.com/qnight/p/8983136.html

时间: 2024-07-30 11:38:05

Java的顺序栈和链式栈的相关文章

java实现顺序栈

顺序栈类的代码: package sequencestack; public class SequenceStack { private int STACK_INIT_SIZE = 5;//栈的原始大小 private int INCREMENT =1;//栈的增量大小 private Object []Stack = null; private int base; private int top; private int stacksize; /** * 初始化栈 * */ void init

数据结构Java实现05----栈:顺序栈和链式堆栈

数据结构Java实现05----栈:顺序栈和链式堆栈 一.堆栈的基本概念: 堆栈(也简称作栈)是一种特殊的线性表,堆栈的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置进行插入和删除操作,而堆栈只允许在固定一端进行插入和删除操作. 先进后出:堆栈中允许进行插入和删除操作的一端称为栈顶,另一端称为栈底.堆栈的插入和删除操作通常称为进栈或入栈,堆栈的删除操作通常称为出栈或退栈. 备注:栈本身就是一个线性表,所以我们之前讨论过线性表的顺序存储和链式存储,对于栈来说,同样适

java实现链栈

前面学习了java实现顺序栈:http://www.cnblogs.com/lixiaolun/p/4644134.html 接下来,学习java实现链栈. 链栈类代码: package linkedstack; public class LinkStack { private Element base; private Element top; class Element { public Object data; public Element next; } /** * 初始化栈 * */

数据结构(java语言描述)顺序栈的使用(两个大数相加)

利用http://www.cnblogs.com/xleer/p/5289661.html中对顺序栈以及栈的进本方法的定义,实现超过整数上限的两个数的加法计算. 算法: package stack;/********************************************************************** * @author sch ********利用栈,计算两个大数的和.大数的值超过int存储的范围******************************

使用JAVA数组实现顺序栈

1,首先总结一下线性表(分为顺序表和链接表,[即顺序存储结构和链式存储结构的区别])和栈(顺序栈和链接栈)还有队列(顺序队列和链接队列)的JAVA类库中的实现: java.util.ArrayList 实现了顺序表,java.util.LinkedList 实现了链接表的功能. java.util.ArrayDeque实现了顺序栈和顺序队列(该类中即定义了与栈操作有关的方法,也定义了与队列操作有关的方法).java.util.LinkedList实现了链接栈和链接队列. 2,定义了一个Stack

Java栈之顺序栈存储结构实现

一.栈的基本定义 栈是一种数据结构,它代表一种特殊的线性表,这种线性表只能在固定一端(通常认为是线性表的尾端)进行插入.删除操作的特殊线性表,通常就是在线性表的尾端进行插入.删除操作. 二.顺序栈的实现 顺序栈是利用一组地址连续的存储单元依次存放从栈底到栈顶的数据元素,栈底位置固定不变,它的栈顶元素可以直接通过顺序栈底层数组的数组元素arr[size - 1]来访问. 1 package com.ietree.basic.datastructure.stack; 2 3 import java.

Java数据结构-线性表之栈(顺序栈和链栈)

栈的定义:(特殊的线性表) ??仅在表的一端进行插入和删除的线性表.允许插入.删除的这一端称为栈顶,另一端称为栈底.表中没有元素时称为空栈. ??被称为后进先出的线性表(Last In First Out),简称 LIFO表,或被称为先进后出的线性表(First In Last Out),简称 FILO表. ??栈更具存储方式的不同分为两种:顺序栈和链栈. 顺序栈: 和顺序表一样,顺序栈也采用数组来存放数据元素: 为了保证栈底位置的不变,采用数组下标为0的位置作为顺序栈的栈底. 而栈顶指针的最大

java堆和栈的区别

在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用. 堆内存用于存放由new创建的对象和数组.在堆中分配的内存,由java虚拟机自动垃圾回收器来管理.在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引

栈的Java实现--链栈

栈的Java实现--链栈 链栈,顾名思义,就是以链表的形式实现的栈的相关操作,其实是功能弱化了的链表,如果已经阅读过链表的实现代码,那么链栈的实现显得更为容易. 链栈的基本结构: 链栈的入栈操作: 让top引用指向新的节点,新节点的next指向原来的top 记录栈内元素个数的size+1 链栈的出栈操作: top引用指向原栈顶元素的下一个元素(top.next),并释放原栈顶元素的引用 记录栈内元素个数的size-1 链栈的Java实现代码: package com.liuhao.DataStr