《大话数据结构》栈的顺序存储及链式存储
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; } }}
测试结果如下
- 一个简单的MySQL数据迁移示例
- MySQL访问受限的问题分析
- 一个Oracle监听问题的网络排查
- MySQL InnoDB Cluster环境搭建和简单测试
- 多平台下的数据存储新秀-PROTOBUF
- TCP的长连接与短连接的含义与区别(附Java代码实现)
- Mycat读写分离配置实践
- 快速搭建主从的脚本和问题排查
- MySQL在RR隔离级别下的unique失效和死锁模拟
- Golang语言--glog日志库使用
- 一个MySQL死锁问题的复现
- Spring Boot 2.0 新特性(一):配置绑定 2.0 全解析
- MySQL断电恢复的一点简单分析
- Spring Boot 2.0 新特性(二):新增事件ApplicationStartedEvent
- 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 数组属性和方法
- Confluence 6 邀请你的小组来使用应用 APP
- 这可能是你见过最好的Redis主从复制原理
- 移动直播集成问题
- TRTC功能咨询
- TKE集群pod镜像拉取失败定位思路
- Android内存管理(JVM 、DVM(dalvik) 、ART简单介绍)
- WordPress 站点地址被恶意篡改的防护方案讨论
- 猿实战06——不一样的地址管理
- Redis常用命令详解
- three.js 制作逻辑转体游戏(下)
- ROS机器人TF基础(坐标相关概念和实践)
- (在模仿中精进数据可视化01) 全国38城居住自由指数可视化
- js字符串/数组常用方法总结
- ThinkPHP5+mpdf 实现富文本生成 PDF文件
- nodejs使用readline逐行读取和写入文件