理解一个复杂概念的最好方法就是把它拆分成小块,并且在完全明白某一 块以后才去着手其他部分。一开始可以某个术语时说得比较模糊,不必去较真它的完整、科学的定义。即便把最权威的解释写下来,但那也仅仅是把它摘抄下来而已,因为我们还没有到达真正理解它的高度。最为一开始的学习,我们不可能就非常严谨、准确,实际上也完全没必要把过多时间浪费在钻牛角尖上,可以让自己理解的不全面,但要保证不犯本质的错误,同时学习的过程不犯错几乎是不可能的。
抽象数据类型
学习数据结构首先可能是要知道有哪些(常用)数据结构。而数据结构的分类本身又是一个非常复杂的事情,由于刚学习,我的理解是按照抽象数据类型的理解来分类,即每个数据类型的使命是什么,即基本操作是什么。
认识ADT
维基百科:抽象数据类型(Abstract Data Type,ADT)是计算机科学中具有类似行为的特定类别的数据结构的数学模型;或者具有类似语义的一种或多种程序设计语言的数据类型。抽象数据类型是间接定义的,通过其上的可执行的操作以及这些操作的效果的数学约束(与可能的代价)。
抽象数据类型包括:(1)数据对象;(2)数据关系;(3)基本操作
//ADT定义:
ADT 抽象数据类型名 {
Data
数据对象的定义
数据元素之间逻辑关系的定义
Operation
操作1(包括操作条件、操作结果描述)
操作2(包括操作条件、操作结果描述)
……
}
//ADT实现
可以通过不同语言实现:
- 用语言已有的数据类型(如String、Number、Boolean)来描述ADT的存储结构
- 用函数定义ADT的操作
//ADT目的
在程序中使用
个人理解
Abstract Data type (ADT) is a type (or class) for objects whose behaviour is defined by a set of value and a set of operations.
抽象数据类型 = 数据 + 对数据的操作
抽象数据类型只关心可以执行什么操作(What),而不关系怎么去执行(How),即不关系这些数据在内存总怎么组织、不关心采用什么算法。
ADT就像一个黑箱,我们只管它能为我们(编程)提供什么操作(Interface),至于这个ADT里面是如何实现的不关心
数据类型与抽象数据结构(date type and ADT)
- date type,原始的数据类型(Number(又可以分成int、float等)、String、Boolean…),仅仅告诉我们这些type能够干嘛。如Number类型可以用来存储数字,
age = 20,String类型可以用来存储我们的姓名myName = "Jack"。但仅仅如此, only with the knowledge that these data type can operate and be performed on without any idea of how they are implemented. - ADT,抽象数据类型,就把数据抽象封装起来,就像一个黑箱,hides the inner structure and design of the data type. 只管它能够提供什么操作。 Now we’ll define three ADTs namely List ADT, Stack ADT, Queue ADT.(也就是一般说的8种类数据结构)
常见数据结构类型
- 数组 Array
- 栈 Stack
- 队列 Queue
- 散列表(哈希表) Hash Table
- 链表 Linked List
- 树 Tree
- 堆 Heap
- 图 Graph
存储结构
在分别分析每种数据结构之前,有必要说明一些存储结构,但目前理解得很浅,仅从在内存中是否连续来理解。
数据是存在内存中的,这点毫无疑问。内存可以理解成很多个内存格子,每个格子上有对应的连续的内存地址(相当于街道号,如大街12号对应的谁家)。内存格子里有东西就表示里面存了数据,空则未存东西。
内个内存格子对应一个内存地址,并且地址号是连续的
存储一个数据肯定是需要很多个格子的,一个格子放不下。如数组arr = [1, 2, 3, 4, 5]需要5个格子来存储,那么为了存放变量arr,我们必须在内存中给5个格子给它,所谓的连续存储就是说这5个格子必须是连续的。同样的占用5个格子的不同数据类型,有的要求这5个格子必须连续,有的则不要求连续。这就是所谓的连续存储方式与非连续(链式)。这里只是粗略分,非连续不等于链式,有很多种。
连续存储要求5个格子连续,非连续存储可以分散在不同格子
那为什么要这样分呢,都连续或者随便分不行嘛,见缝插针不是更利用空间吗?这是因为计算机本身就有跳到任一索引位置(内存地址)的能力,就行你熟悉整条街道一样,不出门就知道12号在哪。于是,如果是连续的,那计算机只需要知道开头的一个地址,根据索引就可以知道与之连着的数据。非连续的则不行,需要跳来跳去,这里以链式存储说明非连续的工作方式。
每个节点需要2个格子,第一个存储数据,第二个链向一下个节点格子(最后一个结点的链是 null,因为它是终点)
每种存储方式存在自有其应用场景,各有各的优势和劣势。主要从操作(如访问、查找、插入、删除)的性能(时间复杂度、空间复杂度)上来考虑。连续存储要求不能有空,这既是优势:能够一步访问任意索引,同时也是劣势:插入和删除操作必须左移补充空位;非连续访问必须从头到尾(单向或者双向),但是其在内存中可以不必连续,插入和删除不用左移补充空位(但需要先访问到)。这里分析的得很笼统,最优情况、最坏情况、平均情况没有考虑、即使同样存储方式的不同类型数据结构也是非常不同的。这是只是说明一点:没有孰优孰劣,各有所长、各有所短而已。概念总结
概念总结
学习每种数据结构之前有必要对之前的概念有一定了解,基本概念包括:
- 数据结构与算法的关系
- 数据结构=逻辑结构+存储结构+运算
- 抽象数据类型=数据对象+数据关系+基本操作
- 存储结构:顺序存储(连续)、链式存储(非连续)
- 常见数据类型:数组、栈、队列、散列表、链表、树、堆、图
数据结构与算法的研究内容
数据结构概念总结
有了基本概念,算是对有什么是数据结构?为什么有这么多种数据结构?有了点认识,至此,可以对常见的几种,其实就是对数据结构A加以一定限制,就成了数据结构B,但是如果B和A都经常用,并且应用场景有区别,那B和A就可以分成两种了(常见的网上多说8种,那自然是有其道理的)
参考资料
- 入门书籍:数据结构与算法图解
- 认识ADT的一篇文章:www.geeksforgeeks.org/abstract-da…
- ADT的视频:青岛大学王卓老师,抽象数据类型的表示与实现