数据结构学习随笔 第一章
绪论
只有清楚数据的内在联系,合理地组织数据,才能对它们进行有效的处理,设计出高效的算法。
1.1 数据结构研究的内容
-
计算机用于数值计算时,一般要经过如下几个步骤:
首先从具体的问题抽象出数学模型,然后设计一个解决此数学模型的算法,最后编写程序,进行测试、调试,直到解决问题。在这个过程中寻求数学模型的实质是分析问题,从中提取出操作的对象,并找出这些操作对象之间的关系,然后用数学语言加以描述,即建立相应的数学方程。 -
数据结构是主要研究非数值计算问题,非数值计算问题无法用数学方程建立数学模型。
1.2 基本概念和术语
- 数据(Data): 客观事物的符号表示。是所有能输入到计算机中并被计算机程序处理的符号的总称。
- 数据元素(Data Element):数据的基本单位,在计算机中通常作为一个整体进行考虑和处理。数据元素用于完整的描述一个对象。
- 数据项(Data Item): 是组成数据元素的,有独立含义的,不可分割的最小单位。
- 数据对象(Data Object):性质相同的数据元素的集合,是数据的子集。
1.2.2 数据结构
数据结构(Data Structure)是相互之间存在一种或多种特定关系的数据元素的集合。数据结构包含逻辑结构和存储结构两个方面。
逻辑结构
数据的逻辑结构是从逻辑关系上对数据进行描述,与数据的存储无关。数据的逻辑结构可以看做是从具体问题抽象出来的数学模型。
数据的逻辑结构有两个要素:一个数据元素,二是关系。数据的关系是指数据元素之间的逻辑关系。
- 数据的逻辑结构
- 线性结构
- 线性表
- 一般线性表
- 线性表
- 特殊线性表
- 栈与队列
- 字符串
- 线性表的推广
- 数组
- 广义表
- 一般线性表
- 线性表
- 非线性结构
- 树结构
- 树
- 二叉树
- 图结构
- 有向图
- 无向图
- 树结构
- 线性结构
存储结构
数据对象在计算机中的存储表示成为数据的存储结构,也称为物理结构。
把数据对象存储到计算机时,通常要求既要存储数据元素的数据,又要存储数据元素之间的逻辑关系,数据元素在计算机内用一个节点来表示。数据元素在计算机中又两种基本的存储结构,分别是顺序存储结构和链式存储结构。
顺序存储结构要求所有的元素依次存放在一片连续的存储空间中,即元素的相对位置来表示数据的逻辑关系。链式存储结构,无需占用一整块存储空间,但是节点附加指针字段,用于存放后继元素的存储地址。
1.2.3 数据类型和抽象数据类型
数据类型
数据类型是一个值的集合和定义在这个值集上的一组操作的总称。
抽象数据类型
抽象就是抽取出实际问题的本质。抽象数据类型一般指由用户定义的、表示应用问题的数学模型,
以及定义在这个模型上的一组操作的总称,其具体包括三部分:数据对象,数据对象上关系的集合以及对数据对象的基本操作的集合。
ADT抽象数据类型的定义:
ADT抽象数据的类型名 {数据对象:(数据对象的定义)数据关系:(数据关系的定义)基本操作:(基本操作的定义)
}
其中,数据对象和数据关系的定义采用数学符号和自然语言描述,基本操作的定义格式为:
基本操作名(参数表)初始条件:(初始条件描述)操作结果:(操作结果描述)
基本操作有两种参数:
- 赋值参数只为操作提供输入值;
- 引用参数(&)除了提供输入值外,还将返回操作结果。
“初始条件”描述了操作执行之前数据结构和参数应满足的条件,若初始条件为空,则省略。“操作结果”说明了操作正常完成之后,数据结构的变化状况和应返回的结果。
1.3 抽象数据类型的表示与实现
1.4 算法和算法分析
1.4.1 算法的定义以及特性
算法是为了解决某类问题而规定的一个有限长的操作序列。
一个算法必须满足一下五个重要特性。
- 有穷性
- 确定性
- 可行性
- 输入
- 输出
1.4.2 评价算法的优劣的基本标准
一个算法的优劣应该从下面的几个方面来评价。
- 正确性
- 可读性
- 健壮性
- 高效性
- 时间高效是指算法设计合理,执行效率高;
- 空间高效是指算法占用存储容量合理;
1.4.3 算法的时间复杂度
算法效率分析的目的是看算法实际是否可行,并在同一问题存在多个算法的情况下,可进行时间和空间性能上的比较,以便于调出较优的算法。
衡量算法效率的方法主要由两类:事后统计法和事前分析估算法。
事后统计法需要先将算法实现,然后测算其时间和空间的开销。
问题规模和语句频度
影响算法时间代价的最主要的因素是问题规模。问题规模是算法求解问题输入量的多少,是问题大小的本质表示,一般用整数n表示。问题规模n对不同的问题含义不同。
一个算法的执行的时间大致上等于其所有语句执行时间的总和,而语句的执行时间则为该条语句的重复执行次数和执行一次所需时间的乘积。
一条语句的重复执行次数称为语句频度。
由于语句的执行要由源程序经编译程序翻译成目标代码,目标代码经装配在执行,因此语句执行一次实际所需要的具体时间是与机器的软硬件环境密切相关的。所以,算法分析并非精确统计算法实际执行需要的时间,二是针对算法中语句的执行次数做出估计,从中得到算法执行时间的信息。
算法的时间复杂度定义
算法中基本语句重复执行的次数是问题规模n的某个函数f(n),算法的时间量度记作:
T(n)=O(f(n))
它表示随着问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近时间复杂度,简称时间复杂度。
数学符号"O"的严格定义为:
若T(n)和f(n)是定义在正整数集合上的两个函数,则T(n)=O(f(n))表示存在正的常数C和N0,使得当n>= N0 时都满足 0 <= T(n) <= C*f(n)。
该定义说明了函数T(n)和f(n)具有相同的增长趋势,并且T(n)的增长至多趋向于函数f(n)的增长。数学符号“O" 用来描述增长率的上限,它表示当问题规模n>=N0时,算法的执行时间不会超过f(n).
算法的时间复杂度分析
分析算法的时间复杂度的基本方法:找出所有语句中语句频度最大的那条语句作为基本的语句,计算基本语句的频度得到问题的规模n的某个函数f(n),取其数量级用符号“O"表示即可。
常见的时间复杂度按照数量级递增排列依次为:
常量阶O(1),对数阶O(log2n),线性对数阶O(n*Log2n), 平方阶O(n^2), 立方阶O(n^3),..., k次方阶O(n^k), 指数阶O(2^n)等。
随着n的增大,T(n)的增长较慢的算法为较优的算法。显然时间负责度为指数阶O(2^n)的算法效率极低,当n值稍大时就无法应用。指数阶的算法尽量避免使用。
最好、最好和平均时间复杂度
算法的时间复杂度不仅与问题的规模有关,还与问题的其他因素有关。
算法在最好的情况下的时间复杂度称为最好时间复杂度,表示的是算法的计算量可能达到最小值。
算法在最坏的情况下的时间复杂度为最坏时间复杂度,表示的是算法计算量可能达到最大值。
算法的平均时间复杂度是指算法在所有可能得情况下,按照输入实例以等概率出现时,算法计算量的加权平均值。
对算法的时间复杂度的度量,我们更关心的是最坏的情况下和平均情况下的时间复杂度。然而在很多的情况下,算法的平均时间复杂度难以确定。因此,通常只讨论算法在最坏情况下的时间复杂度,即分析在最坏情况下,算法执行时间的上限。
1.4.4 算法的空间复杂度
类似于算法的时间复杂度,对算法的存储空间需求,我们采用渐近空间复杂度作为算法所需存储空间的量度,简称空间复杂度,它也是问题规模n的函数,
记作:
S(n)=O(f(n)).
一般情况下,一个程序在机器上执行时,除了需要寄存本身所用的指令、常数、变量和输入数据外,还需要一些对数据进行操作的辅助存储空间。其中,对于输入数据做占据的具体的存储量取决于问题本身,与算法无关,这样只需要分析该算法在实现所需要的辅助空间就可以了。
对于一个算法,其时间复杂度和空间复杂度往往是相互影响的,当追求一个较好的时间复杂度时,可能会导致占用较多的存储空间,即可能会使空间复杂度的性能变差,反之依然。
1.5 小结
- 数据结构是一门研究非数值运算计算程序中操作对象,以及这些对象之间的关系和操作的学科。
- 数据结构包括两个方面的内容:数据的逻辑结构和存储结构,同一逻辑结构采用不同的存储方法,可以得到不同的存储结构。
- 逻辑结构是从具体问题抽象出来的数学模型,从逻辑关系上描述数据,它与数据的存储无关。根据元素之间关系的不同特性,通常有四类逻辑结构:集合结构、线性结构、树形结构和图状结构。
- 存储结构是逻辑结构在计算机中的存储表示,有两种存储结构:顺序存储结构和链式存储结构。
- 抽象数据类型是指由用户定义的、表示应用问题的数学模型,以及定义在这个模型上的一组操作的总称,具体包括三部分:数据对象、数据对象上关系的集合,以及对数据对象的基本操作的集合。
- 算法是为了解决某类问题而规定的一个有限长的操作序列。算法具有五个特性:有穷性、确定性、可行性、输入和输出。一个算法的优劣应该从四个方面来评价:正确性、可读性、健壮性和高效性。
- 算法分析的两个主要方面是分析算法的时间复杂度和空间复杂度,以考察算法的时间和空间效率。一般情况下,鉴于运算空间较为充足,故将算法的时间复杂度作为分析的重点。算法执行时间的数量级成为算法的监禁时间复杂度,T(n)=O(f(n)),它表示随着问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,简称时间复杂度。
练习题
- 简述下列的概念:数据、数据元素、数据项、数据对象、数据结构、逻辑结构、存储结构、抽象数据类型。
- 举一个数据结构的例子,叙述其逻辑结构和存储结构两个层次的含义以及相互关系。
- 简述逻辑结构的四种基本关系并画出他们的关系图。
- 存储结构有哪两种基本的存储方法实现?