《大话数据结构》栈的顺序存储及链式存储
1. 简介
很多男孩子小时候肯定玩过玩具枪,如果你小时候没有玩过那你一定在游乐园里玩过玩具枪打气球的游戏。我小时候玩玩具枪时最喜欢的就是收集子弹,捡邻居家孩子打完后的子弹,这样可以重复利用,我自己也不用花钱买子弹。
想想一下玩具枪上子弹的过程,先取下弹夹,然后将一颗颗的子弹放到弹夹里,然后先被放进去的子弹最后被射出来,最后放进去的子弹最先被射出来。而这种先进后出,后进先出的就是栈。就像玩具枪上子弹一样。每一次取出来的子弹都是最上面的一个,而放入一个子弹也是在最上面。
栈结构如下。
其中top就是指向栈顶的指针,所谓栈顶就是当前栈最上面的数据,也就是当前弹夹中最上面的子弹,而栈底就是最下面的数据,也就是当前弹夹中最下面的子弹。
从上面的图可以发现每一个数据都有前驱和后继,那么实际上栈也是一种线性表,他是一种特殊的线性表,他是只能在一端进行新增数据和获取数据,也没有链表的插入数据和根据某个结点删除数据,而且无论是取数据或者新增都需要在栈顶操作。
既然栈满足线性表那么他一样可以有顺序存储结构和链式存储结构,顺序存储结构我们可以通过数组进行实现,栈底就是索引为0,而栈顶则是当前最新的数据。而使用链式存储可以使用链表,而栈底就是第一个结点,而栈底同样也是最新的数据地址。而顺序存储相比链式存储而言实现起来相对简单一点,但是因为是数组实现所以需要手动扩容,那么就会浪费一些没有使用的空间,而链式存储不需要扩容所以内存的占用没有顺序存储那么大,但是由于每次取出数据时都需要移动top(也就是栈顶),必须要找到上一个数据的地址所以需要遍历链表,那么效率比顺序存储低很多,前提是使用的非双向链表,如果使用双向链表在取数据(出栈)时都是O(1),而使用非双向链表时链表取数据(出栈)则是O(n)。
2. 使用顺序存储结构实现栈
package netty;
/** * 栈的顺序存储 * @author damao * @date 2019-11-27 10:20 */public class OrderStack<T>{
/** * 默认长度为20 */ private Data<T>[] stack = new Data[DEFAULT_CAPACITY];
private Object object = new Object[10];
/** * 默认容量为20 */ private static int DEFAULT_CAPACITY = 2;
/** * 用于指向栈顶,默认指向数组的第0位 */ private int top = 0;
public boolean push(T t){ capacityExpansion (); Data data = new Data (); data.setData (t); stack[top] = data; top++; return true; }
public T pop(){ top--; if(top == -1){ throw new RuntimeException ("Stack is empty"); } T data = stack[top].getData (); stack[top] = null; return data; }
public void capacityExpansion() { if(top >= DEFAULT_CAPACITY){ Data<T>[] newstack = new Data[ DEFAULT_CAPACITY *= 2]; System.arraycopy (stack,0,newstack,0,stack.length); stack = newstack; } }
public static class Data<T>{ private T data;
public T getData() { return data; }
public void setData(T data) { this.data=data; } }}
测试结果如下。
3. 使用链式存储结构实现栈
此处使用的是单向链表,非双向链表。
package netty;
/** * 栈的链式存储 * @author damao * @date 2019-11-27 10:20 */public class LinkedStack<T>{
/** * 用于存放栈顶的地址 */ private Data<T> topData = null;
/** * 链表的起始地址 */ private Data<T> fristData = null;
public boolean push(T t) { if(topData != null){ Data<T> currentData = new Data(null, t); topData.next = currentData; topData = currentData; return true; } Data<T> currentData = new Data(null, t); fristData = topData = currentData; return true; }
public T pop(){ if(topData == null){ throw new RuntimeException("Stack is empty"); } Data<T> result = topData; if(fristData == topData){ topData = null; return result.data; } mobilePointerTop(); return result.data; }
public void mobilePointerTop(){ Data<T> newTopData = fristData; Data<T> previous = fristData; while (newTopData != topData){ previous = newTopData; newTopData = newTopData.next; } topData = previous; }
public static class Data<T>{ Data<T> next; private T data;
public Data(Data<T> next, T data) { this.next=next; this.data=data; } }}
测试结果如下
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- ThinkPHP5.0框架结合Swoole开发实现WebSocket在线聊天案例详解
- PHP封装的page分页类定义与用法完整示例
- Swoole实现异步投递task任务案例详解
- Keras预训练的ImageNet模型实现分类操作
- 通过实例解析Python RPC实现原理及方法
- PHP实现的支付宝支付功能示例
- 为Plesk PHP7启用Oracle OCI8扩展方法总结
- PHP模版引擎原理、定义与用法实例
- python如何查看安装了的模块
- Linux下源码包安装Swoole及基本使用操作图文详解
- python实现简易版学生成绩管理系统
- PHP中localeconv()函数的用法
- 解决pytorch多GPU训练保存的模型,在单GPU环境下加载出错问题
- PHP数据对象映射模式实例分析
- Pytorch 解决自定义子Module .cuda() tensor失败的问题