前言
本篇博文想要介绍的是三种功能单一且最为基础的数据结构:包,栈,队列。相信阅读此篇博客的大部分读者都能够手撕或者直接口述出这三种数据结构的实现方法。本篇博文将会从一般实现方式入手,通过分析优劣点来进一步优化三种数据结构的实现方法。
包,栈,队列的简介
正如前言中所说。包,栈,队列是功能单一的数据结构。
包:一种只能塞值不能取值的结构。即这个类对外暴露的api永远只有add(),没有get()。他的特性在于遍历内部数据时,并不一定需要按照顺序。侧重点在于统计(如求数字的总和,平均值,方差等),而不在于搜索。
举例:你往一个袋子里面放不同重量的黄金。你的最终目的只想要知道最后你拥有多少金子,但是并不总是想着要把黄金按照一定的规律拿出来用。
栈:典型的LIFO(last in first out 后入先出)结构。最后一个add()进去的,在调用pop()方法时,能够第一个获取到。
举例:像是你自己的邮箱。你最后收到的信件,往往是最重要且是被你第一个打开的。
队列:典型的FIFO(first in first out 先入先出)结构。哪个数据先进去,哪个数据先出来。这种现象或者说是流程是我们生活中最普遍的,因为它能够体现公平性
举例:像是在超市排队付款的队伍,谁先排的队伍,谁就能先结账。
包,栈,队列的详细分析
包
SimpleBag
简单的实现思路如下:
1、使用数组作为内部存储容器。每次调用构造方法的时候传入一个size,用于初始化内部数组;
2、根据包的性质设计公用的api:add(),size(),list();
3、内部维护一个数组的下标,每次add的时候就+1。
public class Bag {
/**
* 内部的数据容器
*/
private int[] data;
/**
* data数组的下标 可以初始化为0 也可以初始化为-1 这里初始化为-1举例
*/
private int size = -1;
/**
* 初始化bag
*
* @param maxSize 最大容量
*/
Bag(int maxSize) {
this.data = new int[maxSize];
}
/**
* 往bag里面添加对象
*/
public void add(int item) {
//每次添加对象都应该判断一下是否满了 避免造成数组越界异常
if (!isFull()) {
this.size++;
this.data[this.size] = item;
} else {
throw new RuntimeException("当前bag已满");
}
}
/**
* 当前的bag是否已经满了
*/
private boolean isFull() {
return this.size == this.data.length - 1;
}
/**
* 查看目前bag里面有多少对象了
*/
public int size() {
return this.size;
}
/**
* 展示当前bag里面拥有的数据
*/
public void list() {
for (int dataItem : this.data) {
System.out.print(dataItem + " ");
}
}
public static void main(String[] args) {
//测试用例
Bag bag = new Bag(3);
bag.add(1);
bag.add(2);
bag.add(3);
System.out.println(bag.size());
bag.list();
bag.add(4);
}
上述实现的不足
- 没有考虑数据结构的通用性,如果需要的不是int类型的bag,则需要重新写一份新的bag类。比如StringBag,FruitBag。。。。。。
- 接着第一点讲,如果bag里面存入的是引用类型的数据,那么list()方法作为bag本身提供的api就显得毫无用处。数据结构使用方往往需要在外部获取到每一个对象并对它们做一些逻辑处理;
- 对于一个数据结构来说,我们大多数情况并不希望它默认是定容的,我们希望它在我们无限制add()后能够自我增长maxSize,而不是告诉我它满了。
BetterBag
- 我们需要引入泛型;
- 我们需要支持迭代,简单理解来说,像java提供的Collection一样,需要我们自己实现的数据结构支持foreach语法糖;
- 内部容器需要自动伸缩
public class BetterBag<T> implements Iterable<T> {
/**
* 内部的数据容器
*/
private T[] data;
/**
* data数组的下标 可以初始化为0 也可以初始化为-1 这里初始化为0举例
*/
private int size = -1;
BetterBag(int initialSize) {
//因为java不支持创建泛型数组 所以这么操作
this.data = (T[]) new Object[initialSize];
}
/**
* 往bag里面添加对象
*/
public void add(T item) {
if (isFull()) {
//如果袋子装满了则把容量调整成两倍
adjustBagSize();
}
this.size++;
this.data[this.size] = item;
}
/**
* 查看目前bag里面有多少对象了
*/
public int size() {
return this.size;
}
/**
* 当前的bag是否已经满了
*/