1. 以数据为核心的思维
在现实中计算机能够解决非常多的问题,如图1所示,可以用计算机去实现一个GIS地理信息系统,也可以实现一个电子病历系统,或者实现一个计算机管理资源的图形化界面等。包括现在我们使用的即时通讯软件,浏览器等,能用计算机实现的事情有很多。对于正在学计算机的同学来说,以后也可能会用计算机去做这些事情的,势必也要去设计这样的一个系统。
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/ff01103f24821a5ae73b749065defc92.png)
图1-以数据为核心的思维
对于这些系统,我们通过分析发现它们所具有的的共性就是数据,同时我们在学习计算机时也应该做到这种以数据为核心的思维(也就是计算机思维,学会站在计算机的角度去思考和设计)。
问题是我们如何做到以数据为中心思考,设计?
在图中我们可以看到不同系统的数据都有不同的特点,比如:在GIS地理系统中的数据有自己的一些特点,在电子病历系统中的数据也有自己的一些特点。但是如果我们忽略这些系统表面的这些数据,抓取其本质来看这些系统都是数据,而这种忽略形态,抓本质的就是一种抽象的思维,那么我们在数据结构层面上如何做到忽略形态,抓本质呢?
2. 数据类型
我们先来看一下高级程序语言是如何来表示数据的,在具体的数据类型来看,高级程序语言中一般变量、常量或表达式,都有明确的所属数据类型。比如:int a 就表示我们定义了一个int类型的变量a,其中int就代表具体的数据类型。在C语言中这样的数据类型还有很多,具体如下所示:
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/5dfa3c27ae1f7a2be173316aba6b37fa.png)
图2-C语言中的数据类型
在数据结构中所说的数据元素经常用构造类型中的结构体,数组来表示,而对于数据项来说,都是由基本类型来表示的。当多个基本类型的数据项去描述一个数据元素时,会用构造类型来描述数据元素。在使用高级语言中这些数据类型的时候,不同类型的变量的取值范围不一样,所能做的操作也不一样。
比如:int和double的数据类型就不一样,在描述一个学生的年龄时使用int类型比较合适,身高用double类型,因此我们在用这些数据类型来进行某些操作时就需要选择合适的数据类型,在概括一个数据类型的方面时有两点要考虑:一是类型的取值范围,二是在这个取值范围所能做的操作
。
数据类型在数据结构中的定义是一个值的集合以及定义在这个值集上的一组操作的总称,也是数据类型在数据结构中的本质。但是在高级程序语言中的数据类型是涉及到功能是如何具体实现的,在计算机具体存储,也就是说高级程序语言中的数据类型仍然是属于具体数据类型。
3. 抽象数据类型(Abstract Data Type, ADT)
数据结构中有一个非常重要的概念:即抽象数据类型(Abstract Data Type,ADT)。
抽象数据类型 = 逻辑结构 + 抽象运算,也就是说抽象数据类型是建立在逻辑结构
上的一些抽象的运算
。对于逻辑结构之前有说过,逻辑结构是在普通面前所呈现的形态,并且不涉及到数据在计算机中具体的实现和存储的,对于数据时怎么在计算机中具体的实现和存储的是在存储结构中需要考虑的问题。因为逻辑结构不涉及任何具体的实现,所以在逻辑结构上的抽象运算也不会涉及到具体的实现到在计算机中具体的实现和存储,也就是说,不涉及到具体实现的就是抽象运算。这样做的意义是什么?
对于数据结构中的抽象数据类型来说,抽象数据类型暂不考虑计算机的具体存储结构和运算的具体实现。也就是说我们不需要考虑具体实现的细节,而是把注意力集中到问题的本身去做,抽象数据类型实质上就是在描述问题本身(与计算机无关)
。
于是我们可以知道抽象数据类型在整个的看待问题和分析问题来说简化了很多,因为在抽象数据类型阶段不考虑和计算机有关的因素去描述问题本身的,当把问题本身描述的非常清楚后,然后再做下一环节的问题:基于逻辑结构去设计存储结构,这样我们在分析一个问题就简化了。
抽象数据类型:在不涉及具体的,和计算机系统相关的细节情况下,优先理解问题本身,在此基础上,实现用计算机求解问题的过程。这就是我们使用抽象数据类型的目的
。
在分析一个复杂的问题的时候,如果直接就考虑到计算机的具体实现和存储这些细节时,这个过程需要的环节太多,会觉得难以进行下去。出现这种问题的原因在于没有把思考,分析一个问题分成两个阶段:先抽象数据类型分析清除问题本身,再去考虑问题具体的实现。由此可见数据结构的重要性。
我们在使用抽象数据类型的时候,抽象数据类型(ADT)定义如下所示:
ADT <抽象数据类型名>
{
数据对象:<数据对象的定义>
数据关系:<数据关系的定义>
基本操作:<基本操作的定义>
}
数据对象和数据关系是逻辑结构要关注的问题,基本操作就是抽象运算关注的。
示例:抽象数据类型复数(e1+e2i)
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/90f73e355ec1d5fb267023f4b6764640.png)
图3-抽象数据类型复数(e1+e2i)
通过这个示例我们可以看出,抽象数据类型就是在这种形式化的描述下把数据的组成和如何操作的问题描述清楚,且没有涉及到具体的计算机具体实现的一些问题。而右边是当我们通过抽象数据类型ADT描述清楚问题本身后,然后在此基础上设计高级程序语言中具体实现的过程,在这个阶段涉及到了计算机的具体实现和存储等因素。这也是我们在思考,分析一个问题该有的过程
。
当分析一个复杂的问题,如果直接考虑具体实现和存储的话,这只会让问题更加困难和复杂,我们会认为这是个很难的问题。即便是勉强做到了,但也有可能会对程序后期造成安全隐患。如果我们按照上面这种方式先进行抽象数据类型,然后再考虑具体实现的话,这显然有利于我们分析并解决问题。
4. 数据的抽象与封装
在学习数据结构的时候我们需要理解和明白抽象数据类型的含义,而抽象数据类型中,就是对数据对象和数据运算的声明,将对数据对象的表示和数据运算的实现分离。其中抽象数据类型有两个比较重要的特征:
1. 数据抽象:用ADT描述程序处理的实体时,强调的是其本质的特征、其所能完成的功能,以及它和外部用户的接口。我们需要注意的是:这里在描述数据时忽略了数据的形态,而是一种数据抽象,且不会涉及到高级程序语言中的具体实现和存储。
2. 数据封装:将实体的外部特征和内部实现细节分离,并且对外部用户隐藏其内部实现细节(即抽象数据类型内部的各种定义),对于用户来说只需要使用即可,不需要知道内部的具体实现细节。