zoukankan      html  css  js  c++  java
  • 【Java】 大话数据结构(6) 栈的顺序与链式存储

    本文根据《大话数据结构》一书,实现了Java版的栈的顺序存储结构、两栈共享空间、栈的链式存储机构

    :限定仅在表尾进行插入和删除操作的线性表。

    栈的插入(进栈)和删除(出栈)操作如下图所示。

       

     

    1.栈的顺序存储结构

      用数组存放数据,top变量来指示栈顶元素在数组中的位置(栈顶指针)。一个长度为5的栈的示意图如下:

      实现程序:

    /**
     * 栈的顺序储存结构
     * 
     * 问题:构造器中,泛型数组创建是否有更好的方法?
     * @author Yongh
     *
     */
    public class SqStack<E> {
    	private E[] data;
    	private int top;  //栈顶指针,top=-1时为空栈
    	private int maxSize;
    	private static final int DEFAULT_SIZE= 10;
    	
    	public SqStack() {
    		this(DEFAULT_SIZE);
    	}
    	public SqStack(int maxSize) {
    		//无法创建泛型数组 data=new E[maxSize];
    		data=(E[]) new Object[maxSize];
    		top=-1;
    		this.maxSize=maxSize;
    	}
    	
    	public void push(E e) {
    		if(top==maxSize-1) 
    			throw new RuntimeException("栈已满,无法进栈!");
    		top++;
    		data[top]=e;
    	}
    	
    	public E pop() {
    		if(top==-1)
    			throw new RuntimeException("空栈,无法出栈!");
    		E e=data[top];
    		top--;
    		return e;
    	}
    	
    	public void printStack() {
    		if(top==-1) {
    			System.out.println("空栈");			
    		}else {
    			for(int i=0;i<=top;i++) {
    				System.out.println(data[i]);
    			}
    		}		
    	}
    }
    

      

      测试代码:

    public class StackTest {
    	public static void main(String[] args) {
    		SqStack<Student> sqStack=new SqStack<Student>();		
    	    Student[] students= {new Student("小A",11),new Student("小B",12),new Student("小C",13),
    	            new Student("小D",14),new Student("小E",151)};
    	    for(int i=0;i<5;i++) {
    	    	sqStack.push(students[i]);
    	    }
    	    sqStack.printStack();
    	    for(int i=0;i<5;i++) {
    	    	sqStack.pop();
    	    }
    	    sqStack.printStack();	    
    	}       
    }
    
    class Student{
        public Student(String name, int age) {
            this.name=name;
            this.age=age;
        }
        String name;
        int age;
        public String toString() {
        	return name;
        }
    }
    

      

    小A
    小B
    小C
    小D
    小E
    空栈
    StackTest

    2.两栈共享空间

      通过一个数组存放两个栈,能较好地利用空间。用top1和top2变量表示栈1和栈2的栈顶指针,两个栈的栈底分别位于数组的头部和尾部。

      实现程序(在SqStack程序的基础上稍加改造即可):

    /** 
     * 栈的顺序储存结构(两栈共享空间)
     * 
     * 注意点:栈满条件为top1+1==top2
     * 
     * @author Yongh
     *
     */
    public class SqDoubleStack<E> {
    	private E[] data;
    	private int top1;  //栈1栈顶指针,top=-1时为空栈
    	private int top2;  //栈2栈顶指针,top=maxSize-1时为空栈
    	private int maxSize;
    	private static final int DEFAULT_SIZE= 10;
    	
    	public SqDoubleStack() {
    		this(DEFAULT_SIZE);
    	}
    	public SqDoubleStack(int maxSize) {
    		//无法创建泛型数组 data=new E[maxSize];
    		data=(E[]) new Object[maxSize];
    		top1=-1;
    		top2=maxSize-1;
    		this.maxSize=maxSize;
    	}
    	
    	/*
    	 * 进栈操作,stackNumber代表要进的栈号
    	 */
    	public void push(int stackNumber,E e) {		
    		if(top1+1==top2) 
    			throw new RuntimeException("栈已满,无法进栈!");
    		if(stackNumber==1) {
    			data[++top1]=e;			
    		}else if(stackNumber==2) {
    			data[--top2]=e;			
    		}else {
    			throw new RuntimeException("栈号错误!");
    		}
    
    	}
    	
    	/*
    	 * 出栈操作
    	 */
    	public E pop(int stackNumber) {
    		E e;
    		if(stackNumber==1){
    			if(top1==-1)
    				throw new RuntimeException("空栈1,无法出栈!");
    			e=data[top1--];
    		}else if(stackNumber==2) {
    			if(top2==maxSize-1)
    				throw new RuntimeException("空栈2,无法出栈!");
    			e=data[top2++];
    		}else {
    			throw new RuntimeException("栈号错误!");
    		}
    		return e;
    	}	
    }
    

      

    3.栈的链式存储结构

       通过单向链表实现的栈,栈顶放在单链表的头部(注意进栈操作并不是往链表的后面插入,而是从头部插入)。

      链栈的示意图如下。

      插入与删除操作示意图:

      

      实现程序:

    /**
     * 
     * 栈的链式存储结构
     * 
     * @author Yongh
     */
    public class LinkStack<E> {
    	private StackNode<E> top;
    	private int count;
    	
    	private class StackNode<E>{
    		E data;
    		StackNode<E> next;
    		public StackNode(E data,StackNode<E> next) {
    			this.data=data;
    			this.next=next;
    		}
    	}
    	
    	public LinkStack() {
    		top=new StackNode<E>(null, null);
    		count=0;
    	}
    	
    	public void push(E e) {
    		StackNode<E> node=new StackNode<E>(e, top);
    		top=node;
    		count++;
    	}
    	
    	public E pop() {
    		if(count==0)
    			throw new RuntimeException("空栈,无法出栈!");
    		StackNode<E> node;
    		node=top;
    		top=top.next;
    		count--;
    		E e=node.data;
    		node=null;
    		return e;
    	}
    	
    	public void printStack() {
    		if(count==0) {
    			System.out.println("空栈");			
    		}else {
    			StackNode<E> node=top;
    			for(int i=0;i<count;i++) {
    				System.out.println(node.data);
    				node=node.next;
    			}
    		}		
    	}
    	
    	/*
    	 * 测试代码
    	 */
    	public static void main(String[] args) {
    		LinkStack<Student> linkStack=new LinkStack<Student>();		
    	    Student[] students= {new Student("小A",11),new Student("小B",12),new Student("小C",13),
    	            new Student("小D",14),new Student("小E",151)};
    	    for(int i=0;i<5;i++) {
    	    	linkStack.push(students[i]);
    	    }
    	    linkStack.printStack();	
    	    System.out.println("----");
    	    for(int i=0;i<5;i++) {
    	    	System.out.println(linkStack.pop());
    	    }
    	    linkStack.printStack();	    
    	}
    }
    

      

    小E
    小D
    小C
    小B
    小A
    ----
    小E
    小D
    小C
    小B
    小A
    空栈
    LinkStack

     4.栈的应用

      (1)实现递归

        一些问题(如斐波那契数列的求解),可通过递归函数获得,而递归函数是由栈来实现的。

    典型的斐波那契数列

      (2)四则运算表达式求值

        利用后缀表达式(逆波兰表示法)结合栈可以实现四则运算表达式的求解。而且通过栈,就可以把我们平时用的中缀表达式转化为后缀表达式。    

  • 相关阅读:
    Codeforces Round #380(div 2)
    Codeforces Round #378(div 2)
    Codeforces Round #379(div 2)
    CCPC2016合肥现场赛
    CCPC2016沈阳站
    HDU2222 Keywords Search__AC自动机
    poj2185Milking Grid
    POJ2961_kmp
    POJ 2406
    poj 2752Seek the Name, Seek the Fame
  • 原文地址:https://www.cnblogs.com/yongh/p/9142131.html
Copyright © 2011-2022 走看看