数据结构中的原子、分子和物质

《数据结构中的原子、分子和物质》源站链接,阅读体验更佳~
学习数据结构和算法是写出高效率代码的必由之路,在实际的工作中,我们可能不会亲自去造轮子,比如实现一个排序算法,实现一个红黑树,因为主流语言的库中都包含了常用的数据结构和算法的实现,我们可以直接使用;我们不去亲自造轮子,甚至我们可以没有造轮子的能力,但是,各种各样的轮子具有什么样的特性,适用于什么样的场景我们还是需要了解的,只有这样,我们才能因地制宜,在合适的场景下选择合适的数据结构和算法,提高我们程序的运行效率,达到最好的效果。

提到数据结构,我们自然而然会想到算法,而我们在讨论算法的时候,又会自然而然想到算法所操作的数据结构。实际上,数据结构和算法是密不可分的,好的数据结构可以造就简单高效的算法,而一些算法的实现也依赖于特定的数据结构。我们只谈数据结构,当然是可以的,我们可以在很短的时间内把几种常见的数据结构都介绍一遍。但是事后我们可能没有什么感觉,只有我们把相应的算法也拿出来研究一下,我们可能才会体会到数据结构背后所蕴含的深意。

比如平衡二叉查找树和红黑树都是特殊的树,但是它们对“树”这个结构的约束不同,造就了它们的不同特性,而对一个大类的数据结构施加不同的约束来解决特定问题的现象也是非常常见的。

通过上面的介绍,你可能觉得,数据结构和算法二者之中是不是数据结构占主导地位呢?其实也不尽然,在很多时候,我们的程序想要做什么才是最重要的。我们的程序是接收输入的数据,进行计算然后输出结果的逻辑机器,在程序这道“美味”里,数据就是我们的柴米油盐,算法就是我们的烹饪技艺,二者相辅相成。但是,巧妇难为无米之炊,所以,这里我们先介绍一下数据,文末再来讨论一下数据结构和算法的关系。

什么是数据结构

其实对于数据结构,至今都没有一个被一致公认的定义,不同的人、不同的场景下使用它会有不同的定义,比如我们在使用Java编程的时候会声明很多的类,当我们在讨论业务逻辑的时候往往会把一个类称为一个数据结构,但是在‘数据结构和算法’这个场景中,把一个类称为一个数据结构的说法显然是不太恰当的。

因此,我们在这里讨论数据结构并不是要给数据结构下一个明确的定义,而是要明确‘数据结构与算法’这个话题中,‘数据结构’所研究的问题的边界。

不深究定义不代表不需要理解概念,所以在数据结构中常用的基本术语我们还是要有所概念。

首先就是数据,我们要了解数据结构,当然要知道什么是数据了,数据指的是一切可以被编码之后输入到计算机中,被计算机识别和处理的符号集合,数据不仅仅包含像数字、文本、日期时间等这样的字符型的数据,同时包括像图像、声音、视频等多媒体数据。

现在我们先不考虑像声音、图像这种多媒体数据,就单单说数字、文本这样的字符型数据,相信大家都有一定的编程经验,当我们在程序中对现实世界进行建模的时候,一个单独的字符型数据往往是没有意义的,我们一般会把多个字符型数据放到一起来共同对现实世界中的事物进行描述,比如人,一般会包含姓名、性别、年龄等信息,这个时候,我们称‘人’为数据元素,而‘人’中所包含的姓名、性别、年龄等这些信息成为‘人’这个数据元素的数据项。而当我们把许多人聚合成群进行讨论的时候,就称这群人为一个数据对象,比如‘中国人’就是由‘人’这种数据元素聚合而成的一个数据对象。

上面的描述中我们提到了数据项、数据元素和数据对象这三个概念,这三者比较公认的定义如下:

  • 数据项

    数据项是数据不可分割的最小单位,实际情况中,它可以是一个简单值,也可以是另一种复杂的类型,比如‘人’这个数据元素中,可以包含一个‘地址’元素,地址元素包含省、市、区等数据项,但是在‘数据结构’中我们把数据项视为数据的最小单位是有助于我们解决问题的。

  • 数据元素

    数据元素可以由若干个数据项组成,是组成数据的、有一定意义的基本单位,在计算机中通常作为整体处理,通常也被称为一个记录。注意,虽然数据结构中数据项是不可分割的最小部分,但是数据结构真正的操作对象其实是数据元素,因为我们在数据结构中进行查询、插入、删除、排序等等操作的时候的着眼点其实就是数据元素,但是这些操作依赖于数据元素中的数据项进行计算。

    注意,在一些特殊的场景下一个数据项也可以是一个数据元素,比如100以内的素数中,‘2’这个数据元素本身也是一个数据项。

  • 数据对象

    数据对象是性质相同的数据元素的集合,什么叫性质相同呢?是指数据元素具有相同数量和类型的数据项,比如,还是以人为例,人都有姓名、生日、性别等相同的数据项。

数据项、数据元素和数据对象之间的相互关系如下:

  • 数据项是数据的基本组成单位,它可以单独存在,也可以作为数据元素的一部分。
  • 数据元素是数据结构中的基本单元,它可以由一个或多个数据项组成,用于表示一个实体或概念。
  • 数据对象是具有相同性质的数据元素的集合,它可以包含一个或多个数据元素,用于表示一个实体或概念的集合。

数据对象由数据元素组成,而数据元素由数据项组成,形成了层次关系。这有点类似于物质的原子、分子结构,我们可以使用氢氧原子、水分子和水来类比数据项、数据元素、数据对象之间的关系:

  1. 数据项:数据项可以类比为氢氧元素,它是数据的最小单位。就像氢氧元素是构成水分子的基本元素一样,数据项是组成数据的基本元素。数据项可以是单个的值或多个相关值的集合。
  2. 数据元素:数据元素可以类比为水分子,它是由一个或多个数据项组成的实体。就像一个水分子是由两个氢原子和一个氧原子组成的一样,数据元素是由多个数据项组成的实体。数据元素通常用来表示一个实体或概念,并存储相关的数据信息。
  3. 数据对象:数据对象可以类比为水,它是具有相同性质的数据元素的集合。就像水是由多个水分子组成的一样,数据对象可以包含一个或多个数据元素,并具有一定的关联和组织方式。数据对象用于表示一个实体或概念的集合。

数据结构

至此,有了上面对数据项、数据元素和数据对象的讨论之后,我们可以说一下数据结构研究的是什么问题了,简单来说,数据结构就是解决数据对象的组织和管理问题的。

在我们上面以水为例对数据对象的类比中只是说明了水这种物质可以类比为数据对象,但是别忘了,水可是有固、液、气三态的,而在不同的状态下水具有不同的物理特性。

所以,数据对象和数据结构的关系其实是这样的:

数据对象是具有相同性质的数据元素的集合,而数据结构是指相同性质的数据元素之间的组织关系和操作规则的集合。数据结构描述了如何组织和存储数据,以及如何对数据进行访问、插入和删除等操作。对外,数据结构是一种逻辑结构,提供数据操作的视图,对内,数据结构负责数据元素的物理组织和存储。

简单来说,数据对象是数据结构的实例,数据结构定义了数据对象的逻辑结构和操作规则,而数据对象是数据结构的具体实现,包含了实际的数据元素。

下面,我们就可以把上面以氢氧原子、水分子和水的类比补齐了:

  1. 数据结构:数据结构可以类比为水的特定形态或状态,如液态、固态或气态等。就像不同的水的形态具有不同的组织和性质一样,数据结构描述了数据元素之间的组织关系和操作规则。数据结构定义了数据对象的组织方式和操作规则,包括数据的存储、访问、插入、删除等操作。

有了上面比较感性的认知之后,我们对数据结构下一个比较正式的定义:

数据结构是一门研究非数值计算的程序设计中的操作对象,以及它们之间的关系和操作等相关问题的学科。数据结构是带有结构特性的相同数据元素的集合,它研究的是数据的逻辑结构和数据的物理结构以及它们之间的相互关系,并对这些结构定义相适应的操作,确保结构经过所规定的操作之后仍能保持原有的结构类型。

编程语言中数据的原子、分子和物质

上文中,我们从介绍了一下数据结构的基本概念,对数据结构有了一个定性的认识,其中的数据项、数据元素再到数据对象形成了数据的原子、分子和物质这三个层级。

在落实到具体的编程语言的时候,原子、分子、物质这三层又是如何体现的呢?本文接下来的内容就简单介绍一下编程语言是如何为数据提供结构的。

提到数据结构我们不自觉得会想到数据类型,没错,无论是什么样的数据,无论数据是有结构的还是没有结构的,在高级程序设计语言中都可以体现为一个数据类型,比如Java语言中的java.util.LinkedList这个数据类型就是一个链表的具体实现。

毫无疑问,LinkedList是有结构的,而java.lang.String也是Java中的一个数据类型,但是String是具有结构的数据类型吗?通常,我们把一个String看做一个单纯的值,我们不认为它是具有结构的,无论其底层的实现是怎样的,也无论一个字符串有多长。

单独的一个数字、一个字符串,我们不能说它是有结构的,因为它就是一个单纯的值;而一个数组我们可以认为它是有结构的,因为它包含自己的元素,是一个存放数据的容器。

1976年,瑞士计算机科学家,Algol W,Modula,Oberon 和 Pascal 语言的设计师 Niklaus Emil Wirth写了一本非常经典的书《Algorithms + Data Structures = Programs》,即算法 + 数据结构 = 程序。

这本书主要写了算法和数据结构的关系,对计算机科学产生了深远的影响。同时这本书也阐明了编程语言的两个方面——数据和对数据的操作。

这本书的第一章中,作者基于Pascal语言阐述了他对结构的理解,并且把结构分为了三个层次,分别为标量数据,基本数据结构和高级数据结构

数据中的原子——标量数据

标量数据的特点是其本身只是代表一个数据,不具有结构信息,或者说我们不用考虑它们的底层是如何实现的,不用考虑它们的结构信息,只需要把它们理解为一个简单的值就可以了。最典型的特点就是它可以和一个简单的字符串进行信息无损的相互转化,比如数字、日期时间,以及引用值等等。

比如说Python中,所有的值都是引用类型的,也就是所有的值都是对象,但是其中的一些类型比如数字、字符串,我们可以把它们简单的认为他们只是单纯的值。

标量数据是每一门高级语言都会提供的基础设施,而每一个标量数据都有一个对应的数据类型,标量数据的元数据信息就是由其对应的数据类型所提供的,比如Java中的8大基本数据类型和String类。

标量数据是数据结构中的原子,它是不可再分的,是最终的信息载体。

数据中的分子——基本数据结构

作为数据中分子结构的基本数据结构的主要特征就是其结构稳定,所占存储空间是固定的,所占的存储空间不会随着程序的运行动态变化。

我们都知道,分子其实分为两种情况,一种是不同的原子构成的分子,比如水分子由两个氢原子和一个氧原子构成,另一种是有同一种原子构成的分子,比如足球烯(C60),这是一种非金属单质,是由60个碳原子组成的分子。当然也存在单个原子也可视为分子的情况,比如铁等金属单质。

和现实中的分子类似,基本数据结构为我们提供了把标量数据或者其他的数据结构组合在一起的基本手段,数据之间的组合形式其实一共就只有两种

  • 一种是将多个异构的数据组合成一个有意义的整体,成为一个新的数据类型,本质上其实就是用户自定义数据类型;这类似于水分子这种由不同的原子组成的分子。

  • 另一种组合方式是多个同构的数据组合成一个整体,这有点类似于足球富勒这种单质分子。

    我们会在这个群体中进行一系列的操作,比如遍历每一个成员、从中寻找某一个或者某一些满足某个条件的成员、修改某一个成员的信息、添加一个新成员等等。

对于这两种数据的组合方式,基本数据结构都可以进行支持。常见的基本数据结构只有四种,分别是数组、结构体、元组和联合体。其中数组和结构体是所有的高级语言都会提供或者提供类似特性的基本数据结构,而元组和联合体并不是所有的语言都提供的基本数据结构。

基本数据结构往往是由语言直接提供的基础设施,使用他们其实在很大程度上是在使用语言的编译器,所以基本数据结构都具有一定的静态特性,尤其是在具有静态类型的高级语言中,基本数据结构一经声明之后其结构信息就不能在运行时发生变化了,比如C语言中的数组在声明之后其长度就是固定的,结构体在声明之后其拥有哪些成员也是固定的,并不能在运行时发生变化,Java中的数组和类也是类似的。

下面我们就简单介绍一下每一种基本数据结构,看看它们分别都对哪些数据组合方式提供支持:

  • 数组

    数组是一系列同类型元素的集合,它使用一片连续的存储空间来存储数据,我们可以使用索引的方式对数组中的元素进行随机的访问,数组这种可以随机访问的特性非常重要,比如“散列”这个数据结构,就是利用了数组可以随机访问的特性才能达到近似常量级时间复杂度的搜索。

    数组这种基本数据结构其实是提供了把大量‘同构数据组合成一个群体’这种数据组合方式。

    而且,通常我们都是直接使用数组来表达物理存储结构中的顺序结构。

  • 结构体/对象/类

    结构体在不同的语言中称呼可能有所不同,比如C语言,GoLang中我们称之为结构体,在Java中我们称之为类,而在JavaScript中称作对象,它们在逻辑上其实大体是等价的。结构体中存在成员,每个成员都有自己的名称,我们可以通过结构体成员的名称对结构体中的成员进行随机访问。在很多的实现中,结构体也是使用一段连续的内存进行存储的。

    结构体本质上其实就是用户自定义数据类型,它提供了对‘异构数据组合成一个具有意义的整体’这种数据组合方式的支持。

  • 元组

    元组其实是综合了数组和结构体的特点,和数组类似的,它使用索引的方式对其中的元素进行随机访问;和结构体类似的,它是把异构的数组组合在一起,和结构体不同的是,它其中的成员没有名称,我们可以认为索引就是他们的名称。

    并不是所有的语言都会提供元组这种特性,比如Java,还有一些语言虽然没有直接提供对元组的支持,但是我们可以使用语言的其他特性来实现类似于元组的特性,比如再Kotlin中我们可以利用解构来实现一个元组类,而且在Kotlin中已经使用Data Class这个特性声明了最常用的二元组和三元组。

  • 联合体/共用体

    联合体中可以声明多个成员,每一个成员都有自己的名称,但是在某一个时刻,只有一个成员是活跃的。这就要求联合体所占据的存储空间是它每一个成员所需要的存储空间的最大值。

    提供联合体这种特性的语言并不多,比如C语言就提供了,但是大部分语言都是不提供联合体的。

其实在 《Algorithms + Data Structures = Programs》 一书中,只是提到了数组和结构体这两种基本数据结构,而其书中提出,数组和结构体是每一门高级语言都应该提供的特性,是语言的基础设施。

我们可以认为基本数据结构是数据结构层级中的分子,它具提供了组合原子和其他分子的基本能力。

数据中的物质——高级数据结构

高级数据结构最典型的特征就是**随着程序的运行,它的值和结构可能会发生变化。**因此,实现高级数据结构需要更加复杂的技术,最基本的就是动态内存分配技术。

比如我们通常使用指针把结构中的所有元素链接到一起的手段来实现一个链表,常见的高级数据结构有链表、哈希表、树、图等等。到了高级数据结构这个层面,我们已经开始涉及到数据结构中的逻辑结构了。

我们可以认为高级数据结构是数据结构层级中的物质,它们由分子构成(只通过标量数据的组合是无法形成高级数据结构的),它具有无限的可能性和灵活性。同时我们的数据结构所重点描述的就是高级数据结构。

表示高级结构类型值所需的存储量在编译时是未知的;事实上,它在程序执行过程中可能会发生变化。这需要一些动态存储分配方案,在这种方案中,当相应的值“增长”时,存储会被占用,当值“收缩”时,可能会释放存储用于其他用途。因此,高级结构的表示问题显然是一个微妙而困难的问题,它的解决将严重影响过程的效率和对存储使用的经济性。只有在了解要在结构上执行的原语操作及其执行频率的基础上,才能做出合适的选择。因为语言的设计者和编译器都不知道这些信息,所以建议他从(通用)语言中排除高级结构。

——《Algorithms + Data Structures = Programs》

编程语言一般不会把高级数据结构作为语言的基础设施,而是一般采用标准库的形式对外提供,比如上文中提到过的Java语言中的java.util.LinkedList就是标准库中的一个类,我们也可以基于高级语言所提供的标量数据和基本数据结构这些基础设施来实现自己的高级数据结构。

而高级数据结构,所聚焦的问题其实也是把大量同构的数据组合成一个群体的问题。到了高级数据结构这个层次,基本上对应的就是数据结构中的逻辑结构了,而高级数据结构是使用基本数据结构组合而成,这也就意味着,上文中介绍的基本数据结构实际上是对应了数据结构中的物理结构,其中的数组毫无疑问就是对应的顺序存储结构,而链式存储结构我们需要使用结构体自定义包含指针成员的结构体类型来实现。

总结起来就是,我们在一门高级语言中,使用结构体类似的特性进行数据元素的定义,使用数组类似的特性实现数据结构的顺序存储,在定义数据元素的时候放入指针数据项来实现数据结构的链式存储。

数据结构落实到编程语言中的简单解释

上文中我们已经对数据结构下了一个相对比较正式的定义:数据结构是带有结构特性的相同数据元素的集合。相同的数据元素这个术语映射到编程语言里,其实就像相同数据类型的数据,而不论这个数据类型是一个简单数据类型还是一个复杂数据类型,甚至是一个高级数据结构类型。

而数据结构研究的是数据的逻辑结构和数据的物理结构以及它们之间的相互关系,**并对这些结构定义相适应的操作,确保结构经过所规定的操作之后仍能保持原有的结构类型。**这在编程语言中其实就是对大量相同类型数据进行组织和管理以实现快速的增删查等操作。

一言以蔽之,数据结构落实到编程语言中所研究的问题其实就是是同一种数据类型的大量实例如何组织和管理以实现快速的查找、插入、删除、排序等操作的问题

逻辑结构和物理结构

通过上面的介绍,我们可以知道数据结构包含两个主要的方面,即逻辑结构和物理结构,数据的逻辑结构指的是反映数据元素之间逻辑关系,其中的逻辑关系是指数据元素前后间的关系,而与它们在计算机中的存储位置无关,逻辑结构主要包含以下几个方面:

  • 集合结构:结构中的元素之间除了“属于同一个集合”之外没有其他关系;
  • 线性结构:结构中的元素存在一对一的相互关系,即简单的前后关系;
  • 树形结构:结构中的元素存在一对多的关系;
  • 图形结构:结构中的元素存在多对多的关系。

数据的逻辑结构也是数据结构所重点关注的内容。

而物理结构则是指数据在计算机存储空间中的存放形式,我们这里的存储空间主要是针对计算机内存而言的,像硬盘、光盘这样的外部存储器的数据组织通常用文件结构来描述。

数据的物理结构应该能正确反映数据元素之间的逻辑关系,这才是最为关键的,如何存储数据元素之间的逻辑关系,是实现物理结构的重点和难点,也就是我们编码的重点和难点,因为落到具体的编码的时候,数据结构所做的其实就是如何用具体的物理结构实现抽象的逻辑结构。

数据的物理结构主要有两种形式,即顺序结构和链式结构:

  • 顺序存储结构是把数据存储在连续的内存空间中,其数据元素之间的逻辑关系是通过数据元素在内存中的相对位置来表示的,这个时候,数据元素之间的逻辑关系和物理关系是一致的。
  • 链式存储结构是把数据存放在任意的内存空间中,可以是连续的,也可以是不连续的,数据元素的存储关系不能直接反映它们的逻辑关系,所以需要借助指示元素存储位置的指针来表示数据元素之间的逻辑关系。

再次确定问题边界——只考虑内存且不考虑并发

为了方便后续的讨论,我们在这里要限制一下我们研究问题的上下文。

首先就是我们只考虑应用在内存中的数据结构,众所周知,在冯诺依曼体系结构下的计算机的存储分为内存和外存,对于外存的访问其实是一种成本比较高的IO操作,如果你了解过MySQL的Innodb存储引擎应该就知道,Innodb的索引所采用的数据结构式B+Tree,简单的理解B+Tree就是一个多路平衡树,采用多路树的主要目的其实就是为了减少数据操作时的IO次数,这其中要考虑的技术细节可就相当多了,比如内存的分段和分页,一次IO最多可以从外存中加载多大的数据,要根据这些信息来动态计算树的路等等。如果只是在内存中,n路平衡树的性能和平衡二叉树的性能差距并不大,甚至还赶不上普通的平衡二叉树。

其次就是我们也不会去考虑并发安全的问题,如果要考虑并发安全,需要考虑的技术点同样非常多,比如是否分读写锁、数据扩容的时候是否可以并发进行、扩容期间数据结构是否需要冻结等等。

总而言之,我们主要讨论的是单线程情况下内存中的数据结构和算法,对于其他的场景,属于更高级的进阶内容。

算法和数据结构的关系

这片文章重点的笔墨都用来介绍数据结构了,并没有太多介绍算法的内容,但是这里我还是想阐述一下我对数据结构和算法之间关系的基本理解,为之后的文章做好铺垫。

当计算机在解决一个问题的时候,一般都存在多种不同的方法。对于小型问题,只要管用,采用什么样的方法提现不出太大的差别。但是对于大型问题(或者需要解决大量小型问题的应用),我们就需要设计和选择能够有效利用时间和空间的方法了。

到底是数据结构决定算法还是算法决定数据结构呢?这一直是一个争论不休的话题。其实在《Algorithms + Data Structures = Programs》对数据结构和算法之间的关系进行了比较详细的论述。

我们的程序是由算法和数据结构组成的,而算法是用来操作数据结构的,这就给我们一种直观的感受——数据比算法更重要,**因为我们必须现有一些数据才能对它们进行操作。**确实,算法的实现强烈得依赖于底层的数据结构,而随着我们对数据结构了解的深入,我们也会深刻体会到,不同的数据结构的特性是不一样的,这也就意味着不同的数据结构执行不同的操作的成本是不一样的,比如数组可以随机访问,而链表的随机访问则只能基于遍历来实现。

这是不是就意味着数据结构决定我们所要使用的算法呢?

其实并不是这样的,我们的程序其实是对现实世界的建模,我们总会定义一组数据来代表真实的情况,而这一选择必须以待解决的问题为指导。**也就是说,我们的程序想要做什么,往往更具有决定性。**比如我们可能需要对大量的数据按照一定的顺序进行遍历,又比如我们可能需要能够非常快速定位到某一个特定的数据,这种待解决问题的场景其实就是我们要施加于数据的操作,也就是算法层面的东西了,这样的场景会在一定程度上决定我们所能采用的数据结构。

而数据结构的选择还受限于我们将要用来解决问题的工具——编程语言的限制。而通常来说,这两个方面都是我们所要考虑的。

数据表示的选择通常是相当困难的,它不是由解决问题的工具唯一决定的,它必须总是按照要对数据进行的操作来进行选择。

总的来说,我认为数据结构和算法的关系是这样的:

  • 数据结构是为算法服务的,因为不同的数据结构具有不同的特性,有的数据结构支持的算法,换成另一种结构可能就不行了,比如我们可以对一个有序的数组进行二分查找,但是对于一个有序的链表,我们就无法使用二分查找算法了,因为链表并不支持随机访问。在特定的场景中选择合适的数据结构能够使得我们的程序更加简单高效。
  • **算法需要作用在特定的数据结构之上,**我们所要对数据进行的操作(我们所要采用的算法)反过来驱动我们进行数据结构的选择。我们的每一个场景都会要求对数据做什么样的操作,而想要对数据做特定的操作必须有能够支持这样操作的数据结构的支持,所以算法在一定程度上能决定我们对数据结构的选择。

总的来说数据结构和算法之间的关系并不是简单的谁决定谁的关系,二者其实是一种互为决定的关系,从物理上来说,数据结构决定了算法,而在逻辑意义上,算法决定了我们对数据结构的选择。

数据结构是静态的,它只是组织数据的一种方式。如果不在它的基础上操作、构建算法,孤立存在的数据结构就是没用的。

抽象数据类型(ADT)

上文中,我们提到了,不同的数据结构具有不同的特性,进行不同操作的成本是不一样的,所以对于一个数据结构,它不止包含了结构,还应该包含可以应用于该数据结构的操作,从这个角度来看,我们定义一个数据结构本质上其实也是在定义一个数据类型。我们通常使用抽象数据类型来定义一个数据结构。

抽象数据类型(ADT)是一种能够对使用者隐藏数据表示的数据类型。**抽象数据类型的主要特征在于将数据和操作数据的函数实现关联,并将数据表示隐藏起来。**在使用抽象数据类型的时候我们的注意力集中在API描述的操作上而不会去关注数据的表示;而在我们实现抽象数据类型的时候,我们的注意力集中在数据的表示并实现对数据的各种操作。

如果你熟悉面向对象编程,那么通过上面的描述你就可以知道这不就是面向对象中的封装特性吗。是的,如果我们使用一门基于类的面向对象的编程语言比如Java,定义一个抽象数据类型将是意见非常自然的事情——我们只需要定义一个类就好了。

但是在早期的面向过程的编程语言中,自定义的数据类型只能包含状态而不能包含动作,比如C语言中的结构体,我们如果想在结构体中保存动作,那么就只能在结构体中声明一个指向函数的指针,或者是我们需要使用一种被称作抽象数据类型的伪代码来描述一个数据结构,然后在头文件中定义函数对结构体进行操作。

所以,在介绍数据结构和算法的时候,我使用以类为基础的面向对象的Java语言,Java语言中的一个类(class)就是一个天然的抽象数据类型,或者我们可以使用接口定义一组行为。

总结

本文介绍了我对数据结构的基本看法,从编程语言的层面出发对数据结构中的原子、分子和物质结构层次进行了简单的讨论,同时简单讨论了数据结构和算法之间的关系。

本人深知自己技术水平和表达能力有限,文章中一定存在不足和错误,欢迎与我进行交流(laomst@163.com),跟我一起讨论,修改文中的不足和错误,感谢您的阅读。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

劳码识途

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值