1. 前言
程序员的一天是怎样开启的?
清晨打开储存着各种结构数据的冰箱,从鸡蛋集 “盒” 中提取了一枚数据扔进煎锅,从西兰花树形结构上查找最新鲜的一支跟鸡蛋一起煎熟,从袋装切片面包数组中取出两片,用图形结构的花生酱数据涂抹均匀,撕开新买的养乐多队列 get (0),想要清爽一点可以再从腌黄瓜的栈里 pop () 两片昨天刚放进去的鲜嫩数据。
程序员的世界离不开数据结构,毕竟我们的主要工作内容之一就是用逻辑和算法来处理数据,而合理地使用数据结构就像冰箱里使用恰当的容器来包装食物一样重要。
2. 为什么要学习数据结构
数据结构既是各类考试的必考部分,也是各类公司面试题里的常客,但是如果仅仅是为了以上两点来学习数据结构,那就未免顾此失彼了。其实学习数据结构对我们的工作和学习有着很大的帮助,我大概总结出来我个人感受比较深的几个点跟大家分享:
- 帮助我们有更多更好的手段来使用数据,特别是了解各种数据结构的原理能够帮助我们在实际开发工作中遇到大数据、高性能、大并发等业务场景时选择正确的处理方式;
- 充分发挥计算机的性能,使我们的代码更加高效,在代码优化的过程中可以更明确的在时间维度和空间维度之间做出平衡或选择;
- 学习的过程本身又是提升我们思考问题能力的过程,可以提升我们对算法的了解和认识,拓宽设计思路,同时提升对全局问题思考的格局和高度;
3. 数据结构的定义
百度词条对数据结构(data structure)的定义是:
带有结构特性的数据元素的集合,它研究的是数据的逻辑结构和数据的物理结构以及它们之间的相互关系,并对这种结构定义相适应的运算,设计出相应的算法,并确保经过这些运算以后所得到的新结构仍保持原来的结构类型。
通俗地讲,就是数据元素是以何种形式在计算机上存储,又是以何种形式被程序员使用,它们之间的关系以及我们可以使用的算法。
4. 数据结构的分类
数据结构的分类一般有两种维度,一种是根据数据结构的原理从它们的逻辑结构来区分,一种是从数据结构存储时的物理结构来区分。
逻辑结构,是针对数据之间的相互关系而言的,通常可以分为线性结构和非线性结构。线性结构中的数据元素之间存在着一对一的关系,非线性结构中的数据元素之间存在着一对多或者多对多的关系,而数组中的数据元素相互之间没有任何关系,他们只是同一类型数据的集合。
物理结构,是针对数据在存储器中的存储方法而言的,通常可以分为顺序存储和链式存储。顺序存储的数据是在一段连续的空间中,靠相对位置来表示元素之间的相互关系,像在一个小教室上课的同班同学靠前后座关系就能建立联系;链式存储的数据内存地址不一定是连续的,每一个节点上都有一个指针存储域,靠指针来建立元素之间的相互关系,像几个班级的同学同时上公选课时分散在一个大教室里,同一个班级的同学之间需要靠学号来建立联系。
5. Java 中常用的数据结构
Java 中常用的数据结构都在 java.util 包下,都是对 Collection 和 Map 两个顶级接口的实现类。这里要注意不是 java.util.Collections,Collections 是一个对集合中元素进行查询、排序等操作的工具类,我们下面还会提到。
6. 常用的算法
算法是我们处理数据结构的具体实现步骤,一个好的算法评价标准是效率足够高、存储足够低。我们可以简单地分成增、删、改、查,外加排序五类,排序又可以分为插入排序,交换排序、选择排序、归并排序、分配排序等,而具体实现根据结构和算法的不同,执行的效率也会不同。
好在我们有很多现成的工具可以用可以使我们不必从零开始设计一个健壮、高效、可读性好的优秀的算法。这时候我们可以祭出一个利器 ——java.util.Collections,它实现了对于数据结构的各种静态多态方法来对集合实现搜索、排序、线程安全化等等操作。我们可以从源代码或者官方 API 中了解它都提供了哪些方法。
7. 小结
本节我们简要介绍了数据结构的定义、分类及其算法。大家可以把数据结构理解成我们封装数据的容器,而算法就像是我们对容器中的物品进行查看、添加、使用和整理的思路及方法。本节的内容更多的是需要大家了解和熟悉,后面我们会结合 Java 源码来介绍各类数据结构的特点和用法。