数据结构(1) 绪论
http://jpkc.jnu.edu.cn/sjjg/upload/jiaoyan/
程序=算法+数据结构
程序:为计算机处理问题编制一组指令集。
算法:处理问题的策略。
数据结构:问题的数学模型。
[color=Purple]数据结构讨论描述现实世界实体的数学模型及其上的操作在计算机中的表示和实现。
—————
数据和数据结构
数据:所有能被输入到计算机中,且被计算机处理的符号的集合,是计算机操作的对象的总称,是计算机处理的信息的某种特定的符号表示形式。
数据元素:数据中的一个“个体”,数据结构中讨论的基本单位。
数据项:数据结构中讨论的最小单位,数据元素是数据项的集合。
数据结构:带结构的数据元素的集合。
数据的逻辑结构:线性结构 树形结构 图状结构 集合结构
数据的存储结构——逻辑结构在存储器中的映像。
数据元素的映像方法:用二进制位(bit)的位串表示数据元素。
关系的映像方法:顺序映像 链式映像
抽象数据类型
是指一个数学模型以及在此数学模型上的一组操作。
数据结构+定义在此数据结构上的一组操作=抽象数据类型
抽象数据类型的描述方法:抽象数据类型可用(D,S,P)三元组表示。其中,D是数据对象,S是D上的关系集,P是对D的基本操作集。
ADT 抽象数据类型名{
数据对象:<数据对象的定义>
数据关系:<数据关系的定义>
基本操作:<基本操作的定义>
} ADT 抽象数据类型名
其中,数据对象和数据关系的定义用伪码描述,基本操作的定义格式为
基本操作名(参数表)
初始条件:<初始条件描述>
操作结果:<操作结果描述>
基本操作有两种参数:赋值参数只为操作提供输入值;引用参数以&打头, 除可提供输入值外,还将返回操作结果。
“初始条件”描述了操作执行之前数据结构和参数应满足的条件,若不满足,则操作失败,并返回相应出错信息。
“操作结果”说明了操作正常完成之后,数据结构的变化状况和应返回的结果。若初始条件为空,则省略之。
例: 抽象数据类型三元组的定义:
ADT Complex {
数据对象:D={e1,e2|e1,e2∈RealSet }
数据关系:R1={
| e2 是复数的虚数部分 }
基本操作:
InitComplex( &Z, v1, v2 )
操作结果:构造复数Z,其实部和虚部分别被赋以参数v1和v2的值。
DestroyComplex( &Z)
操作结果:复数Z被销毁。
GetReal( Z, &realPart )
初始条件:复数已存在。
操作结果:用realPart返回复数Z的实部值。
GetImag( Z, &ImagPart )
初始条件:复数已存在。
操作结果:用ImagPart返回复数Z的虚部值。
Add( z1,z2, &sum )
初始条件:z1,z2是复数。
操作结果:用sum返回两个复数z1,z2的和值。
} ADT Complex
数据结构类型的两个特征:数据抽象 数据封装
—————
抽象数据类型的表示和实现
抽象数据类型可以通过固有数据类型(高级编程语言中已实现的数据类型)来实现。
抽象数据类型 类 class
数据对象 数据成员
基本操作 成员函数(方法)
类中的实例被称为对象,对象的状态是唯一的,它由数据成员(属性)的当前值定义,成员函数可通过修改数据成员类改变对象的状态。
在C++中,类的成分(数据成员和成员函数)可以有三种访问级别:
private 私有成分(只允许类的成员函数进行访问)
protected 保护成分(只允许类的成员函数及其子孙类进行访问)
public 公有成分(允许类的成员函数、类的实例及其子孙类、子孙类的实例进行访问)
面向对象的程序设计
所谓“程序设计”即是计算机模拟现实世界的活动。
从传统的角度看,程序是“活动”的集合,程序=过程+调用,称这种程序设计方法为面向过程的程序设计。
现实世界是由许许多多的实体或对象构成的。这些对象彼此相关并能相互通讯,对象的活动构成了现实世界的活动。
从面向对象的角度看,程序是对象的集合;对象之间的相互作用构成了一个软件系统。
对象参与的交互动作称为事件,在事件中消息在对象之间发送,接收消息的对象调用相应的方法进行响应。
—————
算法和算法的衡量
算法是为了解决某类问题而规定的一个有限长的操作序列。
一个算法必须满足以下五个重要特性:
1.有穷性 对于任意一组合法输入值,在执行有穷步骤之后一定能结束,即:算法中的每个步骤都能在有限时间内完成;
2.确定性 对于每种情况下所应执行的操作,在算法中都有确切的规定,使算法的执行者或阅读者都能明确其含义及如何执行。并且在任何条件下,算法都只有一条执行路径;
3.可行性 算法中的所有操作都必须足够基本,都可以通过已经实现的基本操作运算有限次实现之;
4.有输入 作为算法加工对象的量值,通常体现为算法中的一组变量。有些输入量需要在算法执行过程中输入,而有的算法表面上可以没有输入,实际上已被嵌入算法之中;
5.有输出 它是一组与“输入”与确定关系的量值,是算法进行信息加工后得到的结果,这种确定关系即为算法的功能。
算法设计的原则
设计算法时,通常应考虑达到以下目标:
1.正确性
首先,算法应当满足以特定的“规格说明”方式给出的需求。
其次,对算法是否“正确”的理解可以有以下四个层次:
a.程序中不含语法错误;
b.程序对于几组输入数据能够得出满足要求的结果;
c.程序对于精心选择的、典型、苛刻切带有刁难性的几组输入数据能够得出满足要求的结果;
d.程序对于一切合法的输入数据都能得出满足要求的结果;
通常以第c层意义的正确性作为衡量一个算法是否合格的标准。
2. 可读性
算法主要是为了人的阅读与交流,其次才是为计算机执行。因此算法应该易于人的理解;另一方面,晦涩难读的程序易于隐藏较多错误而难以调试;
3.健壮性
当输入的数据非法时,算法应当恰当地作出反映或进行相应处理,而不是产生莫名奇妙的输出结果。并且,处理出错的方法不应是中断程序的执行,而应是返回一个表示错误或错误性质的值,以便在更高的抽象层次上进行处理。
4.高效率与低存储量需求
通常,效率指的是算法执行时间;存储量指的是算法执行过程中所需的最大存储空间。两者都与问题的规模有关。
算法效率的衡量方法和准则
通常有两种衡量算法效率的方法:
事后统计法
缺点:1.必须执行程序
2.其它因素掩盖算法本质
事前分析估算法
和算法执行时间相关的因素:
1.算法选用的策略
2.问题的规模
3.编写程序的语言
4.编译程序产生的机器代码的质量
5.计算机执行指令的速度
一个特定算法的“运行工作量”的大小,只依赖于问题的规模(通常用整数量n表示),或者说,它是问题规模的函数。
假如,随着问题规模n的增长,算法执行时间的增长率和f(n)的增长率相同,则可记作:
T (n) = O(f(n))
称T (n) 为算法的(渐近)时间复杂度
算法 = 控制结构 + 原操作
(固有数据类型的操作)
从算法中选取一种对于所研究的问题来说是基本操作的原操作,以该基本操作在算法中重复执行的次数作为算法运行时间的衡量准则。
算法的存储空间需求
算法的空间复杂度
S(n) = O(g(n))
表示随着问题规模n的增大,算法运行所需存储量的增长率与g(n)的增长率相同。
算法的存储量包括:
1.输入数据所占空间;
2.程序本身所占空间;
3.辅助变量所占空间。
若输入数据所占空间只取决与问题本身,和算法无关,则只需要分析除输入和程序之外的额外空间。
若所需额外空间相对于输入数据量来说是常数,则称此算法为原地工作。
若所需存储量依赖于特定的输入,则通常按最坏情况考虑。
- 易中天对话王立群“一庄一谐”
- 数据结构(2) 线性表