一、开篇说明
本场 Chat 主要以 Java 语言结合 JDK 1.8 相关源码来说明数据结构和一些常用的算法,不断提高自身内功修为。从线性表、队列和栈一直到树结构结合源码实例来进行说明,在上一篇 Chat《Java 编程(30 条建议)》中讲了在编程过程中要注意的一些部分,这一节准备以数据结构结合一些实例说明再到算法概念的基础讲解和一些举例说明。通过这些基础东西的研究,后面会针对再写一些关于 Java 开发框架相关的讲解,到后面我们会发现往往最难的是逻辑而不是工具框架的使用技能。
什么是数据结构:数据之间相互存在的一种或多种特定的关系的元素的集合。
在 Java 开发数据结构可是说是算法的基础,也就是说只有在熟悉数据结构的基础上,进行相应的算法设计才能写出好的算法。
二、数据结构
通常数据结构分为逻辑结构、物理结构。逻辑结构是指数据对象中数据元素之间的相互关系,而物理结构是指数据的存储结构。
逻辑结构主要是集合结构、线性结构、树形结构、图形结构。
物理存储结构主要是链式存储和线性存储。
Java 线性表
结构
在 Java 语言中大家都知道,线性表 ArrayList 和 LinkedList 两种。对于这两种数据结构的优缺点肯定是前者查询速度快、后者插入和删除速度快,这里不进行赘述。
下面使用一张图片来展示线性表的线性存储结构:
(图片来源:线性存储结构)
以上图为例,作为线性存储时,数据的每一个下标位置都是独立的,比如我们在进行删除操作时删除线性表中的一个数据 a1,那么紧跟着 a2 就会变成 a1,a3 就会变成 a2,以此类推,这样删除一个数据那么每个数据的位置都会发生改变。同样的在进行插入操作时也会产生这种影响,因此,像 Java 中的 ArrayList 就适合运用在查询相关的操作。
接下来我们再看线性表的链式存储结构。
链式存储结构:
(图片来源:链式存储结构)
相比线性存储结构,链式结构可以通过附加变量的形式指向前一个或者后一个数据对象类似于 C 语言中指针的形式,这样以来我们在删除数据或者是添加数据的时候就可以只改变前后相邻的两个变量。所以这就是为什么 Java 中的 LikedList 适用于做添加和删除操作。
Java 实现
首先来看 ArayList 和 LinkedList 在 Java 中的实现过程以及查看它的内部成员方法都是如何实现的,通过一部分的代码的说明来深入理解他们的数据结构。
1. ArrayList 对象类内部方法实现过程分析
ArrayList 继承并且实现的接口有哪些?我们通过查看它的源码结构,可以看到如下面代码块中的内容:
public class ArrayList extends AbstractList
implements List, RandomAccess, Cloneable, java.io.Serializable
{
}
ArrayList 构造方法:
/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
构造方法中定义集合长度,在默认情况下自动扩展长度。有时候为了节约内存的消耗,定义 List 时可以给它一个长度,但前提是长度必须是我们够用的。