zoukankan      html  css  js  c++  java
  • 数据结构>栈 小强斋

    栈与队列(一)

    栈和队列是两种重要的数据结构。从栈与队列的逻辑结构上来说,它们也是线性结构,与线性表不同的是它们所支持的基本操作是受到限制的,它们是操作受限的线性表,是一种限定性的数据结构。

    一、栈

    1.1栈的定义和抽象数据类型

    栈(stack)又称堆栈,它是运算受限的线性表,其限制是仅允许在表的一端进行插入和删除操作,不允许在其他任何位置进行插入、查找、删除等操作。表中进行插入、删除操作的一端称为栈顶(top),栈顶保存的元素称为栈顶元素。相对的,表的另一端称为栈(bottom)。

    当栈中没有数据元素时称为空栈;向一个栈插入元素又称为进栈或入栈;从一个栈中删除元素又称为出栈或退栈。由于栈的插入和删除操作仅在栈顶进行,后进栈的元素必定先出栈,所以又把堆栈称为后进先出表(LastIn First Out,简称LIFO)。

    一个堆栈及数据元素插入和删除的过程。

    Stack接口

    package 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;
    }
    

    其中涉及的异常类定义如下:

    StackEmptyException堆栈为空时出栈或取栈顶元素抛出此异常

    package stack;
    
    //StackEmptyException 堆栈为空时出栈或取栈顶元素抛出此异常
    public class StackEmptyException extends RuntimeException {
    	public StackEmptyException(String err) {
    		super(err);
    	}
    }
    

    1.2 栈的顺序存储实现

    和线性表类似,堆栈也有两种基本的存储结构:顺序存储结构和链式存储结构。

    顺序栈是使用顺序存储结构实现的堆栈,即利用一组地址连续的存储单元依次存放堆栈中的数据元素。由于堆栈是一种特殊的线性表,因此在线性表的顺序存储结构的基础上,选择线性表的一端作为栈顶即可。根据数组操作的特性,选择数组下标大的一端,即线性表顺序存储的表尾来作为栈顶,此时入栈、出栈等操作可以在Ο(1)时间完成。

    由于堆栈的操作都在栈顶完成,因此在顺序栈的实现中需要附设一个指针top 来动态的指示栈顶元素在数组中的位置。通常top 可以用栈顶元素所在数组下标来表示,top=-1 时表示空栈。堆栈在使用过程中所需的最大空间很难估计,因此,一般来说在构造堆栈时不应设定堆栈的最大容量。一种合理的做法和线性表的实现类似,先为堆栈分配一个基本容量,然后在实际的使用过程中,当堆栈的空间不够时再倍增存储空间,这个过程所需的时间均摊到每个数据元素时间为Θ(1),不会影响操作实现的时间复杂度。

    package stack;
    
    public class StackArray implements Stack {
    	private final int LEN = 8; // 数组的默认大小
    	private Object[] elements; // 数据元素数组
    	private int top; // 栈顶指针
    
    	public StackArray() {
    		top = -1;
    		elements = new Object[LEN];
    	}
    
    	// 返回堆栈的大小
    	public int getSize() {
    		return top + 1;
    	}
    
    	// 判断堆栈是否为空
    	public boolean isEmpty() {
    		return top < 0;
    	}
    
    	// 数据元素e 入栈
    	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;
    	}
    
    	// 栈顶元素出栈
    	public Object pop() throws StackEmptyException {
    		if (getSize() < 1)
    			throw new StackEmptyException("错误,堆栈为空。");
    		Object obj = elements[top];
    		elements[top--] = null;
    		return obj;
    	}
    
    	// 取栈顶元素
    	public Object peek() throws StackEmptyException {
    		if (getSize() < 1)
    			throw new StackEmptyException("错误,堆栈为空。");
    		return elements[top];
    	}
    }
    

    1.3 栈的链式存储实现

    链栈即采用链表作为存储结构实现的栈。当采用单链表存储线性表后,根据单链表的操作特性选择单链表的头部作为栈顶。

    不带头结点的单链表实现堆栈的示意图(a1最后入栈)

    package stack;
    
    //Stack 的链式存储实现
    public class StackSLinked implements Stack {
    	private SLNode top; // 链表首结点引用
    	private int size; // 栈的大小
    
    	public StackSLinked() {
    		top = null;
    		size = 0;
    	}
    
    	// 返回堆栈的大小
    	public int getSize() {
    		return size;
    	}
    
    	// 判断堆栈是否为空
    	public boolean isEmpty() {
    		return size == 0;
    	}
    
    	// 数据元素e 入栈
    	public void push(Object e) {
    		SLNode q = new SLNode(e, top);
    		top = q;
    		size++;
    	}
    
    	// 栈顶元素出栈
    	public Object pop() throws StackEmptyException {
    		if (size < 1)
    			throw new StackEmptyException("错误,堆栈为空。");
    		Object obj = top.getData();
    		top = top.getNext();
    		size--;
    		return obj;
    	}
    
    	// 取栈顶元素
    	public Object peek() throws StackEmptyException {
    		if (size < 1)
    			throw new StackEmptyException("错误,堆栈为空。");
    		return top.getData();
    	}
    }

    其中节点的定义如下

    package stack;
    
    public class SLNode {
    	private Object element;
    	private SLNode next;
    
    	public SLNode() {
    		this(null, null);
    	}
    
    	public SLNode(Object ele, SLNode next) {
    		this.element = ele;
    		this.next = next;
    	}
    
    	public SLNode getNext() {
    		return next;
    	}
    
    	public void setNext(SLNode next) {
    		this.next = next;
    	}
    
    	/**************** Methods of Node Interface **************/
    	public Object getData() {
    
    		return element;
    	}
    
    	public void setData(Object obj) {
    		element = obj;
    	}
    }


     

     

  • 相关阅读:
    Bootstrap模态框modal的高度和宽度设置
    入门学习Linux常用必会命令实例详解
    Linux 系统中用户切换(su user与 su
    hdu 3549 Flow Problem(最大流模板题)
    第三章 学后心得及总结 【物联网1132-11】
    Find Minimum in Rotated Sorted Array 旋转数组中找最小值 @LeetCode
    面试题4
    Fp关联规则算法计算置信度及MapReduce实现思路
    POJ 1679 The Unique MST 推断最小生成树是否唯一
    论程序猿的社会地位
  • 原文地址:https://www.cnblogs.com/xiaoqiangzhaitai/p/5429420.html
Copyright © 2011-2022 走看看