数据结构的本质就在于:如何将现实世界中各种各样的数据放入到内存中,并且如何在内存中操作这些数据,如何评价这些存储方案和操作方法。
数据结构难学吗?是难学。
为什么难学?一开始上来就讲空间复杂度、时间复杂度,就讲抽象数据,当然难学了。
1、生活、生产等现实世界的数据有各种各样的组成形式。例如一个课程的所有学生的成绩(一组数据),一个班全部学生的所有课程的成绩(一张表)、一个单位的人员结构(树)等等。
2、这些数据都要先加载到内存中,再送到CPU中进行计算。
3、内存的最基本单位叫做存储单元,一个字节(不讨论理论中的、个别情况的)。存储单元相当于一个空盒子,可以放置数据。为了便于管理,盒子会给一个编号,当然存储单元也会有编号,其实就是地址。理论上地址的方案可以有多种(计算机组成原理和操作系统的任务),不过对于程序员来说,这些都跟我们无关,为了简单起见,我们把存储单元的编号(地址)都编成0、1、2、3、4,......这样的,于是这些编号或地址的取值范围,我们就称地址空间。这个地址空间,跟一维坐标轴一样,所以是一维线性空间。
4、很明显,数据就是一个个放入到这些存储单元中,就象我们把一个单位的物品放入盒子一样。现在,假设一个盒子只能装入一个单位的物品。因而,一个存储单元也只能放入一个单位的数据。
5、接下来,假设说,我们有很多很多的空盒子(X个)。有一天,我们要将若干单位物品(N个)放入盒子中,那么我们可以在一个盒子放入一个单位物品。依此类推,我们可以在一个存储单元中放置一个单位的数据。
6、再接下来,我们有两种放置方案:一个挨一个地连续地放置物品;当然,也可以不连续地放置物品。依此类推,在内存当中放置数据,也有两种方案,连续地放置数据,或者不连续地放置数据。为什么会有不连续的放置方案呢?原因很简单,一个主要的原因是,内存的空间利用率高,碎片少(操作系统的存储管理的知识,且不用理会),删除旧有的数据很容易(这个是数据结构的内容)。
7、现在,可以把这两个将数据放入到存储单元的方案叫做物理存储。对连续物理存储方案来说,事情比较好办,通过编号(索引、下标)就可以找到物品,对于不连续的方案,那么我们就要在一个物品上面标记下一个物品的位置,这个标记就是下一个物品的地址(指针)。当然,在计算机中,指针的记录本身也要占用内存的存储单元,所以我们在c语言中用结构体把数据和指针组织成为一个单位。通过这个指向关系,我们可以在不连续的放置方案中依次地查找我们所需要的东西(物品或数据)。
8、接下来,就象我们经常进行从盒子当中查询物品、取用物品或增加物品等操作一样,我们也要进行从内存当中查询数据、取用(删除)数据或增加数据等操作。那么,对于不同的物理存储方案来说,其方法是不一样的。这个想一想,我们如何对付真实的物品,我们就如何对付内存中的数据。这就是数据的物理存储方案的数据操作。
9、好了,搞懂这些,字符串之类的知识点就不难了。
10、记住一点,只有两种物理存储结构:连续的和不连续的,因为内存的存储单元的地址(编号)是0、1、2、3......(一维地址空间、或者线性地址空间)。
11、是不是只有物理存储结构(方案)就可以了呢?在第1条中说过,现实当中的数据是有各种各样的结构的。而在第10条,我们强调了物理放置方案只有2种:连续的和不连续的。
12、于是就产生一个问题,如何将现实世界当中的关系各种各样的数据放入到内存之中。
13、解决第12条中的问题,我们可以分两步走,第1步是将现实世界的数据组织成为逻辑结构,第2步再把逻辑结构的数据映射到物理结构中。
14、显然,在第1步中,我们抛去数据的其它属性,只留下数据的两个属性就可以了:一个属性是数据的值,另一个属性就是数据之间的关系。这两个属性就得到一个逻辑结构:graph(图),这就是离散数学中的图论。那么,这就是科学家的事情,他们负责针对具体的问题,将现实世界的数据构造出对应的graph(图)。
15、在第2步中,我们要做的事情,把这个graph映射到物理存储结构中,这就是数据结构要做的事情了。显然,我们可以用数组来存储,也可以用链表来存储,回忆一下最短路径算法的两个做法。ps.,二维数组、三维数组也是一个连续存储的结构,在c语言debug下,看看地址就知道了。那么,不连续的存储结构,也就是链表,当然有很多的衍生:双向链表、十字链表、等等。
16、显然,不管现实世界中的数据之间的关系如何,我们都可以用graph来描述,只不过是,不同的数据关系有不同的结构而已,比如:树、森林、mesh,等等。
17、当然,我们要掌握一些常见的graph的操作方法,最主要就是搜索方法。而且还要注意,这些方法是分两个层次的,一个物理存储结构这个层次,一个是逻辑存储结构这个层次的。那么现在,深度优先搜索、广度优先搜索是哪个层次呢?
18、当然,我们还要掌握一下存储结构的压缩。
19、到了这个时候,我们还要问一下,各种方案的优劣性质如何,也就是空间复杂度和时间复杂度了。
20、当然,我们这个时候,还要进一步的问一问,能不能将这些逻辑结构给出一个统一的描述,那么,就是抽象数据了。
21、当然,我们还要掌握逻辑存储结构的各种树的优化,特别是针对不同的应用,比如红黑树、B树。
22、当然,我们最后还要学习一下外存的存储结构。
23、当然,实验是少不了的。自己debug一下内存单元的地址,并且在纸上手工的画一下是最好了。
24、最后,有了这些基础,剩下也就好办了。
25、不推荐教材。尤其是国外的教材,先容许我默默地吐一下槽,各种知识点零碎不堪,不成体系,不成系统。
编辑于 2015-09-14
作者保留权利