zoukankan      html  css  js  c++  java
  • 大话数据结构七:两栈共享存储空间(双向栈)

    1. 为什么要使用双向栈?

    通过上一篇博客 - 特殊的线性表(栈),不难知道栈的顺序存储(数组实现)性能相对较高,因为它不存在插入和删除时移动元素的问题,但是它有一点缺陷:要实现确定数组存储容量的大小,万一不够,需要扩充容量。这时双向栈就派上用场了,它可以最大限度的利用事先开辟的存储空间。


     

    2. 双向栈有什么特点?

    数组有两个端点,两个栈有两个栈底,让一个栈的栈底为数组的始端,即下标为0处,另一个栈为数组的末端,即下标为数组长度m-1处。这样,两个栈如果增加元素,就是两端点向中间延伸(如下图)。



    3. Java实现双向栈

     

    // 双向栈的数组实现
    public class ShareStack<T> {
    	private Object[] arr; // 数组实现栈的操作
    	private int top1; // 栈1: 栈顶指针
    	private int top2; // 栈2: 栈顶指针
    	private static Integer DEFAULT_SIZE = 16; // 数组默认长度
    	private static final Integer STACK_1 = 1; // 栈1
    	private static final Integer STACK_2 = 2; // 栈2
    
    	public ShareStack() {
    		init();
    	}
    
    	public ShareStack(int size) {
    		DEFAULT_SIZE = size;
    		init();
    	}
    
    	// 初始化栈
    	public void init() {
    		arr = new Object[DEFAULT_SIZE];
    		this.top1 = -1;
    		this.top2 = DEFAULT_SIZE;
    	}
    
    	// 压栈
    	public boolean push(int stackNum, T data) {
    		if (top1 + 1 == top2) { // 栈已满
    			System.out.println("栈已满,不能再push元素了..");
    			return false;
    		}
    		if (stackNum == STACK_1) { // 操作的是栈1
    			arr[++top1] = data; // 栈1前进一位
    			return true;
    		} else if (stackNum == STACK_2) { // 操作的是栈2
    			arr[--top2] = data; // 栈2后退一位
    			return true;
    		} else {
    			System.out.println("请输入正确的栈编号: 1 或 2");
    			return false;
    		}
    	}
    
    	// 弹栈
    	@SuppressWarnings("unchecked")
    	public T pop(int stackNum) {
    		if (stackNum == STACK_1) { // 操作的是栈1
    			if (top1 == -1) {
    				System.out.println("栈1已经是空栈...");
    				return null;
    			}
    			return (T) arr[top1--]; // 栈1后退一位
    		} else if (stackNum == STACK_2) { // 操作的是栈2
    			if (top2 == DEFAULT_SIZE) {
    				System.out.println("栈2已经是空栈...");
    				return null;
    			}
    			return (T) arr[top2++]; // 栈2前进一位
    		} else {
    			System.out.println("请输入正确的栈编号: 1 或 2");
    			return null;
    		}
    	}
    
    	// 获取栈顶元素
    	@SuppressWarnings("unchecked")
    	public T getTop(int stackNum) {
    		if (stackNum == STACK_1) {
    			if (this.top1 != -1) {
    				return (T) arr[top1];
    			}
    		} else if (stackNum == STACK_2) {
    			if (stackNum != DEFAULT_SIZE) {
    				return (T) arr[top2];
    			}
    		} else {
    			System.out.println("请输入正确的栈编号: 1 或 2");
    		}
    		return null;
    	}
    
    	// 获取数组长度
    	public int size() {
    		return DEFAULT_SIZE + top1 + 1 - top2;
    	}
    
    	// 判断是否为空栈
    	public boolean isEmpty() {
    		return this.top1 == -1 && this.top2 == DEFAULT_SIZE;
    	}
    
    	// 置为空栈
    	public boolean clear() {
    		this.top1 = -1;
    		this.top2 = DEFAULT_SIZE;
    		return true;
    	}
    	
    	// 测试方法
    	public static void main(String[] args) throws Exception {
    		ShareStack<Integer> stack = new ShareStack<Integer>();
    		stack.push(1, 1);
    		stack.push(2, 2);
    		stack.pop(1);
    		stack.pop(2);
    	}
    }

    4. 什么时候使用双向栈

     

    1.) 两个栈的空间需求有相反关系时,也就是当一个栈增长时另一个栈在缩短的情况。

    2.) 两个栈需要具有相同的数据类型,如果数据类型不同,将会使问题复杂化。



  • 相关阅读:
    [NOI2003],[AHOI2006]文本编辑器
    luogu P5151 HKE与他的小朋友
    [NOI2005]维护数列
    [HNOI2012]永无乡
    luogu P4146 序列终结者
    [SCOI2016]美味
    UVA1451 Average
    [JSOI2007]字符加密
    luogu P3809 【模板】后缀排序
    CentOS 7系统启动后怎么从命令行模式切换到图形界面模式
  • 原文地址:https://www.cnblogs.com/riasky/p/3360826.html
Copyright © 2011-2022 走看看