1. 数据结构的基本概念
数据:是信息的载体,能够被计算机识别、存储和处理的符号集合。可以是数字、字符、图像、声音等。
数据元素:是数据的基本单位,通常作为一个整体进行处理。例如,在学生信息表中,一个学生的所有信息(学号、姓名、成绩等)构成一个数据元素。
数据项:是构成数据元素的最小单位。例如,学生信息中的“学号”或“姓名”是一个数据项。
数据对象:是具有相同性质的数据元素的集合。例如,所有学生的信息构成一个数据对象。
数据结构:是数据元素之间的关系及其操作的集合。
数据结构是指按⼀定的逻辑结构组成的⼀批数据,按某种存储结构将这批数据存储于计算机中,并在这批数 据上定义了⼀个运算集合。
数据结构包括以下三个方面:
- 逻辑结构:数据元素之间的抽象关系。
- 存储结构:数据在计算机中的存储方式。
- 运算:对数据元素的操作,如插入、删除、查找等。
2. 数据的逻辑结构
数据的逻辑结构是从问题抽象出来的模型,描述数据元素之间的逻辑关系,与数据的存储无关。
逻辑结构可以分为两大类:线性结构和非线性结构。
具体来说,逻辑结构包括以下四种基本结构:
2.1 集合结构
定义:数据元素之间除了“属于同一集合”外,没有任何其他关系。
特点:
- 元素之间是独立的,没有特定的逻辑关系。
- 集合结构的操作主要包括并集、交集、差集等。
示例:数学中的集合,如{1, 2, 3, 4}。
2.2 线性结构
定义:数据元素之间存在一对一的线性关系,即除了第一个和最后一个元素外,每个元素都有唯一的前驱和后继。
特点:
- 元素之间是顺序关系,形成一条“线”。
- 常见的线性结构包括:数组、链表、栈、队列、串等。
示例:
- 数组:元素在内存中连续存储,通过下标访问。
- 链表:元素通过指针链接,存储空间可以不连续。
2.3 树形结构
定义:数据元素之间存在一对多的层次关系,形成一个树状结构。
特点:
- 元素之间是层次关系,每个元素有一个父节点和零个或多个子节点。
- 常见的树形结构包括:二叉树、B树、堆、哈夫曼树等。
示例:
- 二叉树:每个节点最多有两个子节点。
文件系统:文件夹和文件之间的层次关系。
2.4 图状结构
定义:数据元素之间存在多对多的任意关系,形成一个网状结构。
特点:
- 元素之间的关系可以是任意的,没有严格的层次或顺序。
- 常见的图状结构包括:有向图、无向图、带权图等。
示例:
- 社交网络:用户之间的关系可以是任意的。
交通网络:城市之间的道路连接。
2.5.1 线性结构
定义:
线性结构元素之间是一对一的关系,在线性结构中只有一个开始结点和一个终端结点,其他的每一个结点有且仅有一个直接前驱和一个直接后继。
线性结构是指数据元素之间存在一对一的关系,即数据元素按顺序排列,形成一个线性序列。每个元素(除了第一个和最后一个)都有且仅有一个前驱和一个后继。
特点:
- 顺序性:元素按顺序排列,逻辑上是一个接一个的。
- 唯一性:
- 第一个元素没有前驱,最后一个元素没有后继。
- 其他元素有且仅有一个前驱和一个后继。
- 简单性:结构简单,易于实现和操作。
常见类型:
- 线性表:
- 最基本的线性结构,包括顺序表和链表。
- 例如:数组、单链表、双向链表。
- 栈(Stack):
- 后进先出(LIFO)的结构,只能在栈顶进行插入和删除操作。
- 队列(Queue):
- 先进先出(FIFO)的结构,队尾插入,队头删除。
- 字符串(String):
- 由字符组成的线性序列。
应用场景:
- 线性表:存储和处理线性数据,如学生成绩表。
- 栈:函数调用栈、表达式求值、括号匹配。
- 队列:任务调度、缓冲区管理、广度优先搜索(BFS)。
2.5.2 非线性结构
定义:
非线性结构是指数据元素之间存在一对多或多对多的关系,是更复杂的层次或网状结构。
非线性结构是指数据元素之间存在一对多或多对多的关系,即元素之间的关系不再是简单的线性顺序,而是更复杂的层次或网状结构。
特点:
- 复杂性:元素之间的关系复杂,可能有多重关联。
- 灵活性:可以表示更复杂的数据关系。
- 多样性:有多种不同的组织形式,如树、图等。
常见类型:
- 树(Tree):
- 层次结构,每个元素(节点)有且仅有一个父节点,但可以有多个子节点。
- 例如:二叉树、二叉搜索树、堆、哈夫曼树。
- 图(Graph):
- 网状结构,元素(顶点)之间可以有多对多的关系。
- 例如:有向图、无向图、加权图。
- 集合(Set):
- 元素之间没有明显的顺序关系,通常用于存储唯一值。
- 多维数组:
- 数据元素在多维空间中的排列,例如矩阵。
应用场景:
- 树:文件系统、数据库索引、组织架构。
- 图:社交网络、地图导航、网络拓扑。
- 集合:数据去重、字典、过滤唯一值。
对比总结
| 特性 | 线性结构 | 非线性结构 |
|---|---|---|
| 数据关系 | 一对一 | 一对多或多对多 |
| 结构复杂度 | 简单 | 复杂 |
| 常见类型 | 线性表、栈、队列、字符串 | 树、图、集合、多维数组 |
| 应用场景 | 线性数据处理、简单任务调度 | 复杂数据关系、层次或网状结构 |
| 操作复杂度 | 通常较低 | 通常较高 |
3. 数据的存储结构
存储结构是逻辑结构在计算机中的实现方式,描述了数据元素及其关系在内存中的存储形式。常见的存储结构包括:
3.1 顺序存储
定义:数据元素存储在连续的存储单元中,通过元素的相对位置来表示逻辑关系。
特点:
- 存储密度高,支持随机访问。
- 插入和删除操作效率低,需要移动大量元素。
示例:数组。
3.2 链式存储
定义:通过指针将数据元素链接起来,元素在内存中可以不连续存储。
特点:
- 插入和删除操作效率高,只需修改指针。
- 存储密度较低,不支持随机访问。
示例:链表。
3.3 索引存储
定义:通过索引表存储数据元素的地址,索引表中的每一项指向一个数据元素。
特点:
- 查找效率高,但需要额外的存储空间。
- 适用于大数据量的查找操作。
示例:数据库索引。
3.4 散列存储
定义:通过散列函数计算数据元素的存储位置,将数据元素直接存储在计算出的地址中。
特点:
- 查找效率高,但可能发生冲突。
- 适用于快速查找和插入的场景。
示例:哈希表。
3.5.1存储密度高 / 存储密度大
定义:存储密度高或存储密度大表示在存储结构中,数据元素占用的实际存储空间与总存储空间的比率较高,即存储空间的利用率高。
特点:
- 数据元素占用的存储空间较多,而额外的开销(如指针、索引等)较少。
- 适合需要高效利用内存的场景。
示例:
- 数组:数组的元素在内存中连续存储,没有额外的空间开销,存储密度高。
- 顺序存储结构:数据元素在内存中按顺序存放,存储密度大。
3.5.2存储密度低 / 存储密度小
定义:存储密度低或存储密度小表示在存储结构中,数据元素占用的实际存储空间与总存储空间的比率较低,即存储空间的利用率低。
特点:
- 数据元素占用的存储空间较少,而额外的开销(如指针、索引等)较多。
- 适合需要动态插入和删除操作的场景。
示例:
- 链表:链表的每个节点除了存储数据元素外,还需要额外的空间存储指针,存储密度低。
- 链式存储结构:数据元素通过指针链接,存储密度小。
3.5.3对应关系总结
| 术语 | 含义 | 特点 | 示例 |
|---|---|---|---|
| 存储密度高 / 存储密度大 | 存储空间利用率高 | 数据元素占用空间多,额外开销少 | 数组、顺序存储 |
| 存储密度低 / 存储密度小 | 存储空间利用率低 | 数据元素占用空间少,额外开销多 | 链表、链式存储 |
3.5.4应用场景
- 存储密度高 / 存储密度大:适用于需要高效利用内存的场景,如数组、顺序存储结构。
- 存储密度低 / 存储密度小:适用于需要动态插入和删除操作的场景,如链表、链式存储结构。
3.6 存储结构与逻辑结构的关系
- 存储结构是逻辑结构在计算机中的实现方式,不同的逻辑结构可以选择不同的存储结构。
- 例如,线性结构可以选择顺序存储(数组)或链式存储(链表),树可以选择链式存储(二叉树)或顺序存储(堆)。
4. 数据结构的运算
数据结构的运算是对数据元素的操作,常见的运算包括:
- 插入:在数据结构中添加新元素。
- 删除:从数据结构中移除元素。
- 查找:在数据结构中寻找特定元素。
- 更新:修改数据结构中的元素。
- 排序:按特定顺序排列数据结构中的元素。
运算的效率取决于数据结构的逻辑结构和存储结构。例如,在数组中查找元素的时间复杂度为O(1),而在链表中查找元素的时间复杂度为O(n)。
5. 算法与算法分析
算法:解决特定问题的有限步骤。算法必须满足以下特性:
- 有穷性:算法必须在有限的步骤内结束。
- 确定性:算法的每一步必须有明确的定义。
- 可行性:算法的每一步都必须是可行的。
- 输入:算法有零个或多个输入。
- 输出:算法有一个或多个输出。
算法的时间复杂度:衡量算法执行时间的增长率,常用大O表示法。例如,O(1)表示常数时间复杂度,O(n)表示线性时间复杂度。
算法的空间复杂度:衡量算法所需存储空间的增长率,同样使用大O表示法。
6. 评判算法的好坏
评判算法的好坏通常从以下几个方面进行:
6.1 正确性
- 定义:算法能够正确地解决问题,产生预期的输出。
- 重要性:正确性是算法最基本的要求,一个错误的算法无论效率多高都没有意义。
6.2 时间效率
- 定义:算法执行所需的时间,通常用时间复杂度来衡量。
- 重要性:时间效率直接影响算法的运行速度,尤其是在处理大规模数据时。
6.3 空间效率
- 定义:算法执行所需的存储空间,通常用空间复杂度来衡量。
- 重要性:空间效率影响算法的内存占用,特别是在内存有限的系统中。
6.4 可读性
- 定义:算法的代码是否易于理解和维护。
- 重要性:可读性高的算法更易于调试、修改和扩展。
6.5 健壮性
- 定义:算法在输入非法数据或异常情况下是否能够正确处理。
- 重要性:健壮性强的算法能够在各种异常情况下保持稳定运行。
7. 综合应用
结合习题中的内容,以下是一些重要的知识点和示例:
7.1 时间复杂度分析
示例1:
Cfor(i=1;i<=n;i++)for(j=1;j<=i;j++)x=x+1;- 分析:内循环的执行次数与外循环有关,总执行次数为1+2+3+…+n = n(n+1)/2,时间复杂度为O(n²)。
示例2:
C i = 1; while(i <= n) i = i * 3;- 分析:i的值按指数增长,时间复杂度为O(log₃n)。
7.2 逻辑结构与存储结构的应用
- 线性结构:适用于顺序处理的问题,如数组、链表、栈、队列等。
- 非线性结构:适用于层次化或复杂关系的问题,如树、图等。
总结
第一章介绍了数据结构的基本概念、逻辑结构、存储结构、运算以及算法分析。逻辑结构包括集合结构、线性结构、树形结构和图状结构,存储结构包括顺序存储、链式存储、索引存储和散列存储。评判算法的好坏通常从正确性、时间效率、空间效率、可读性和健壮性等方面进行。掌握这些知识点是学习更复杂数据结构和算法的基础。