栈的顺序存储和链式存储
Posted duan2
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈的顺序存储和链式存储相关的知识,希望对你有一定的参考价值。
栈和队列是两种重要的数据结构。从栈与队列的逻辑结构上来说,它们也是线性结构,
与线性表不同的是它们所支持的基本操作是受到限制的,它们是操作受限的线性表,是一种
限定性的数据结构。栈(stack )又称堆栈,它是运算受限的线性表,其限制是仅允许在表的一端进行插入和删除操作,
不允许在其他任何位置进行插入、查找、删除等操作。表中进行插入、删除操作的一端称为 栈顶(top) ),
栈顶保存的元素称为 栈顶元素。相对的,表的另一端称为栈底(栈底(bottom)
Stack接口
Stack接口 public interface Stack { //返回堆栈的大小 public int getSize(); //判断堆栈是否为空 public boolean isEmpty(); //数据元素 e 入栈 public void push(Object e); //栈顶元素出栈 public Object pop() throws StackEmptyException; //取栈顶元素 public Object peek() throws StackEmptyException; }
顺序存储结构实现
顺序栈是使用顺序存储结构实现的堆栈,即利用一组地址连续的存储单元依次存放堆栈
中的数据元素。由于堆栈是一种特殊的线性表,因此在线性表的顺序存储结构的基础上,选
择线性表的一端作为栈顶即可。根据数组操作的特性,选择数组下标大的一端,即线性表顺
序存储的表尾来作为栈顶,此时入栈、出栈等操作可以在Ο(1)时间完成。
由于堆栈的操作都在栈顶完成,因此在顺序栈的实现中需要附设一个指针 top 来动态的
指示栈顶元素在数组中的位置。通常 top 可以用栈顶元素所在数组下标来表示,top= -1 时表
示空栈。
堆栈在使用过程中所需的最大空间很难估计,因此,一般来说在构造堆栈时不应设定堆
栈的最大容量。一种合理的做法和线性表的实现类似,先为堆栈分配一个基本容量,然后在
实际的使用过程中,当堆栈的空间不够时再倍增存储空间,这个过程所需的时间均摊到每个
数据元素时间为Θ(1),不会影响操作实现的时间复杂度
public class StackArray implements Stack { private final int LEN = 8; //数组默认大小 private Object[] elements; //数据元素数组 private int top; //栈顶指针 public StackArray() { top = -1; elements = new Object[LEN]; } //返回堆栈大小 @Override public int getSize() { return top + 1; } //判断堆栈是否为空 @Override public boolean isEmpty() { return top < 0; } /** *对元素入栈 */ @Override public void push(Object e) { if (getSize()>=elements.length){ expandSpace(); elements[++top]=e; } } private void expandSpace() { Object[] a = new Object[elements.length*2]; for (int i=0; i<elements.length; i++) a[i] = elements[i]; elements = a; } /** *栈顶元素出栈 */ @Override public Object pop() throws StackEmptyException { if (getSize()<1){ throw new StackEmptyException("错误,堆栈为空"); } Object obj = elements[top]; elements[top--]=null; return obj; } @Override public Object peek() throws StackEmptyException { if (getSize()<1) throw new StackEmptyException("错误,堆栈为空。"); return elements[top]; } }
栈的链式存储实现
链栈即采用链表作为存储结构实现的栈。当采用单链表存储线性表后,根据单链表的操
作特性选择单链表的头部作为栈顶,此时,入栈、出栈等操作可以在Ο(1)内完成。由于堆
栈的操作只在线性表的一端进行,在这里使用带头结点的单链表或不带头结点的单链表都可
以。使用带头结点的单链表时,结点的插入和删除都在头结点之后进行;使用不带头结点的
单链表时,结点的插入和删除都在链表的首结点上进行
ublic class StackSLinked implements Stack { private SLNode top; //链表首节点引用 private int size; public StackSLinked() { top=null; size=0; } @Override public int getSize() { return size; } @Override public boolean isEmpty() { return size==0; } @Override public void push(Object e) { SLNode q=new SLNode(e,top); top=q; size++; } @Override public Object pop() throws StackEmptyException { if (size<1){ throw new StackEmptyException("错误,堆栈为空"); } Object obj = top.getData(); top=top.getNext(); size--; return obj; } @Override public Object peek() throws StackEmptyException { if (size<1){ throw new StackEmptyException("错误,堆栈为空"); } Object obj = top.getData(); return obj; } }
以上是关于栈的顺序存储和链式存储的主要内容,如果未能解决你的问题,请参考以下文章