数据结构第二讲
合集下载
(第二讲)数据库(第二章:关系数据库的基本概念)
表2-5 学生表 XS_Sex XS_Age ZY_Id
类型 char(10) char(10) char(2) Int char(4) 学号,主码 姓名:字符类型
说明
性别:只能为男或女 年龄:整形 所在专业编号,外码,参照专业表
4. 选课表(XK_Tab):记录学生的选课结果,对于任意一门课,每 个学生一年最多只能选一次,因此用课程编号、学号和年份联合作为 选课表的主码。选课表通过学号参照学生表,通过课程编号参照课程 表。
2. 课程表(KC_Tab):存放多门课程,主码为课程编号。
表2-4 课程表(KC_Tab)
列名 KC_Id KC_Name KC_KC_Id KC_Point
类型 char(4) char(50) char(4) Float
说明 课程编号,主码 课程名称 先修课课程编号 课程的学分
3. 学生表(XS_Tab):记录学生的基本信息,主码为学号,通过专业 编号参照专业表。
2.3 关系模型规范化
关系模型规范化的目的是为了消除存储异常,减少数据冗余, 保证数据的完整性和存储效率。 关系数据库中的关系是要满足一定的规范化要求的。对于不 同规范化程度,可以使用“范式”来衡量。满足最低要求的为I范 式。。在I范式的基础上,进一步满足一些要求的为II范式,以次 类推。一般情况下,在实践中关系模式满足3范式就基本可以。
元素的每一个值 di 叫作一个分量。关系模型中要求每一 个分量必须属于某种基本数据类型,如整形或字符串型。
关系:笛卡尔积的子集就是一个关系。
R( D1 , D2 ,, Dn )
这里R表示关系的名字,n是关系的目或度。
例: 我们给出如下三个域: D1 =导师集合。导师={王新,赵阳} D2=专业集合。专业={计算机,通信} D3=学生集合。学生={(张三,101),(李四,201)} 则笛卡尔积为: D1XD2XD3={(王新,计算机,张三,101), (王新,计算机,李四,201),
类型 char(10) char(10) char(2) Int char(4) 学号,主码 姓名:字符类型
说明
性别:只能为男或女 年龄:整形 所在专业编号,外码,参照专业表
4. 选课表(XK_Tab):记录学生的选课结果,对于任意一门课,每 个学生一年最多只能选一次,因此用课程编号、学号和年份联合作为 选课表的主码。选课表通过学号参照学生表,通过课程编号参照课程 表。
2. 课程表(KC_Tab):存放多门课程,主码为课程编号。
表2-4 课程表(KC_Tab)
列名 KC_Id KC_Name KC_KC_Id KC_Point
类型 char(4) char(50) char(4) Float
说明 课程编号,主码 课程名称 先修课课程编号 课程的学分
3. 学生表(XS_Tab):记录学生的基本信息,主码为学号,通过专业 编号参照专业表。
2.3 关系模型规范化
关系模型规范化的目的是为了消除存储异常,减少数据冗余, 保证数据的完整性和存储效率。 关系数据库中的关系是要满足一定的规范化要求的。对于不 同规范化程度,可以使用“范式”来衡量。满足最低要求的为I范 式。。在I范式的基础上,进一步满足一些要求的为II范式,以次 类推。一般情况下,在实践中关系模式满足3范式就基本可以。
元素的每一个值 di 叫作一个分量。关系模型中要求每一 个分量必须属于某种基本数据类型,如整形或字符串型。
关系:笛卡尔积的子集就是一个关系。
R( D1 , D2 ,, Dn )
这里R表示关系的名字,n是关系的目或度。
例: 我们给出如下三个域: D1 =导师集合。导师={王新,赵阳} D2=专业集合。专业={计算机,通信} D3=学生集合。学生={(张三,101),(李四,201)} 则笛卡尔积为: D1XD2XD3={(王新,计算机,张三,101), (王新,计算机,李四,201),
《数据结构》课件第二章
线性表的基本操作(逻辑)
➢ 构造一个空表L ➢ 获取L的长度(即元素个数) ➢ 访问L中第i个数据元素的值 ➢ 访问L中第i个数据元素的前驱/后继的值 ➢ 在L中第i个元素之前插入新的元素e ➢ 删除L的第i个数据元素
➢ 注意在插入或者删除之后,线性表的长度应 能随之改变
一 顺序存储
➢ 线性表的顺序表示:用一组地址连续的存储单 元依次存储线性表的数据元素。
否
将Temp_b插入到 LC的第k个位置上
Temp_a ≤ Temp_b
是 将Temp_a插入到 LC的第k个位置上
否 i ≤ LA.len 否
j← j + 1
i← i + 1
j ≤ LB.len
Temp_a = Temp_b
是
否
否
j← j + 1
k← k + 1
结束
是
将LA表的第i个元 素插入到LC表的
插入操作的时间复杂度 O(n/2) 链表中的插入、删除操作没有上溢的情况, 并且节省内存资源
思考:若现已知道指向某元素节点的指针 p,希望能在该节点之前插入元素x,该如 何操作?其算法时间复杂度是多少?
3) 单链表的删除
p
删除第i个元素,由e返回值 删除b
a
Hale Waihona Puke bc … 1) 寻找第i-1个结点
2) 保留结点b的地址
9 SHI 5
0
1
1 ZHAO 2
2 QIAN 3
3 SUN 4
4 LI
9
5 ZHOU 6
6 WU 8
7 ZHENG 8
8 WANG 0
9 SHI 5
i=s[i].cur 指针后移
数据结构02
5 循环及出口语句
(4) Loop 语句串 forever 实例(C#没有对应语句): i0 sum 0 loop sum sum + i i I +1 if (i>=100) exit forever
5 循环及出口语句
(4) Exit语句
C#对应语句:break c#实例: float sum = 0; string[] StudNames = { "张三", "李四", "王五", "陈六" }; for (int i = 0; i < StudNames.Length;i++ ) { if (StudNames[i] == "王五") break; }
4 条件及分支语句
(2)分支语句 语法格式: Case :条件1:语句串1 :条件2:语句串2 … :条件n:语句串n :else: 语句串n+1 End
5 循环及出口语句
(1) While 循环条件 do 语句串 end C#实例: int i = 0; float sum = 0; while (i <= 100) { sum = sum + i; i += 1; }
第二讲 SPARKS语言
提纲 1 计算机语言概述 2 SPARK语言概述 3 赋值语句 4 条件及分支语句 5 循环及出口语句 6 输入/输出语句 7 子程序 8 停止语句
1计算机语言概述
计算机语言与自然语言 常用计算机语言
各种Shell语言 SQL(Structure Query Language) C,C++,C#,Java,VB,Delphi 汇编语言 机器语言
数据结构第二章
操作结果:构造一个空线性表L。
Destroylist(&L)
初始条件:线性表L已存在。
操作结果:销毁线性表L。
ClearList(&L)
初始条件:线性表L已存在。 操作结果:将线性表L臵为空表。
四、抽象数据类型线性表的定义
Listempty(L) 初始条件:线性表L已存在。
操作结果:若L为空,则返回TRUE,否则返回FALSE。 ListLength(L) 初始条件:线性表L已存在。 操作结果:返回L中数据元素个数。 GetElem(L,i,&e) 初始条件:线性表L已存在。 操作结果:用e返回L中第i个数据元素的值。 LocateElem(L,e,compare()) 初始条件:线性表L已存在。 操作结果:返回L中第1个与e满足关系compare()的数 据元素的位序。若这样的元素不存在,则返回值为0。
四、抽象数据类型线性表的定义
上述类型定义中的操作均为“原子操作”,利用 这些“原子操作”可以完成其他更复杂操作。 例2-1 设两个线性表LA和LB分别表示两个集合A和B, 现要得到一个新的集合A=A∪B(并)。 此问题可演绎为对线性表作如下操作:
扩大线性表LA,将存在于线性表LB中而不存在于线
性表LA中的数据元素插入到LA中。
四、抽象数据类型线性表的定义
ListInsert(&L,i,e) 初始条件:线性表L已存在,1≼i ≼ ListLength(L)+1 。 操作结果:在L中第i个位臵之前插入新的数据元素e,L 的长度加1。 ListDelete(&L,i,&e) 初始条件:线性表L已存在, 1≼i ≼ ListLength(L) 。 操作结果:删除L的第i个数据元素,并用e返回其值,L 的长度减1。 }ADT List
第2讲数据结构与算法概要PPT课件
分治与递归像一对孪生兄弟,经常同时应用在 算法设计之中,并由此产生许多高效算法。
.
7
2.1 递归的概念
例1 阶乘函数 非递归定义:n!=n*(n-1)*(n-2)*…*1 阶乘函数可递归地定义为:
边界条件
n!n(n11)!
n0 n0
递归方程
边界条件与递归方程是递归函数的二个要素,递归函
数只有具备了这两个要素,才能在有限次计算后得出
A(n,m)的自变量m的每一个值都定义了一个单变量函数:
M=0时,A(n,0)=n+2
M=1时,A(n,1)=A(A(n-1,1),0)=A(n-1,1)+2,和A(1,1)=2故 A(n,1)=2*n
M=2时,A(n,2)=A(A(n-1,2),1)=2A(n-1,2),和 A(1,2)=A(A(0,2),1)=A(1,1)=2,故A(n,2)= 2^n 。
第2章 递归与分治策略
.
1
学习要点: • 理解递归的概念。 • 掌握设计有效算法的分治策略。 • 通过下面的范例学习分治策略设计技巧。 • (1)二分搜索技术; • (2)大整数乘法; • (3)Strassen矩阵乘法; • (4)棋盘覆盖; • (5)合并排序和快速排序; • (6)线性时间选择; • (7)最接近点对问题; • (8)循环赛日程表。
.
2
算法总体思想
对将这要k求个解子的问较题大分规别模求的解问。题如分果割子成问k题个的更规小模规仍模然的不子够问 小题,。则再划分为k个子问题,如此递归的进行下去,直 到问题规模足够小,很容易求出其解为止。
T(n)
=nቤተ መጻሕፍቲ ባይዱ
T(n/2)
T(n/2)
.
T(n/2)
.
7
2.1 递归的概念
例1 阶乘函数 非递归定义:n!=n*(n-1)*(n-2)*…*1 阶乘函数可递归地定义为:
边界条件
n!n(n11)!
n0 n0
递归方程
边界条件与递归方程是递归函数的二个要素,递归函
数只有具备了这两个要素,才能在有限次计算后得出
A(n,m)的自变量m的每一个值都定义了一个单变量函数:
M=0时,A(n,0)=n+2
M=1时,A(n,1)=A(A(n-1,1),0)=A(n-1,1)+2,和A(1,1)=2故 A(n,1)=2*n
M=2时,A(n,2)=A(A(n-1,2),1)=2A(n-1,2),和 A(1,2)=A(A(0,2),1)=A(1,1)=2,故A(n,2)= 2^n 。
第2章 递归与分治策略
.
1
学习要点: • 理解递归的概念。 • 掌握设计有效算法的分治策略。 • 通过下面的范例学习分治策略设计技巧。 • (1)二分搜索技术; • (2)大整数乘法; • (3)Strassen矩阵乘法; • (4)棋盘覆盖; • (5)合并排序和快速排序; • (6)线性时间选择; • (7)最接近点对问题; • (8)循环赛日程表。
.
2
算法总体思想
对将这要k求个解子的问较题大分规别模求的解问。题如分果割子成问k题个的更规小模规仍模然的不子够问 小题,。则再划分为k个子问题,如此递归的进行下去,直 到问题规模足够小,很容易求出其解为止。
T(n)
=nቤተ መጻሕፍቲ ባይዱ
T(n/2)
T(n/2)
.
T(n/2)
数据结构课件-第二章
1初始化单链表 Void InitList(LinkList *head) {/* 初始化单链表 */ head=(LinkList)malloc(Sizeof(ListNode)) /*申请头结点空间,并使头指针head指向头结点 */ head->next=NULL; /* 置链尾标记NULL */ }
2.4线性表的链式存储结构
链式存储结构用一组任意的存储单元依次存储 线性表里元素,这组存储单元可以是连续的, 也可以是不连续的,甚至是零散分布在内存的 任何位置上。
为反映出各元素在线性表中的逻辑关系,对每 个数据元素来说,除了存储其本身的信息之外 ,还需存储一个指示其直接后继的信息(即直 接后继的存储位置)。这两部分信息组成一个 数据元素的存储映象,称为结点(Node)。
例如,图2-4-2所示为线性表(dog,pig,cat,fox,hen,bat ,bee,bird)的单链表存储结构,整个链表的存取需从头指针开始 进行,依次顺着每个结点的指针域next找到线性表的各个元素,直 至next域为空为止。
通常我们用箭头表示链域中的指针:
typedef struct Node {ElemType data; /*数据域*/ struct Node *next; /*指针域*/ }ListNode,*LinkList;
2.3.1 线性表的顺序存储
线性表的顺序存储是指用一组地址连续的存储单元依 次存储线性表中的各个元素,使得线性表中在逻辑结 构上相邻的数据元素存储在相邻的存储单元中 。
假设线性表中有n个数据元素,每个数据元素占K个 存储单元,第一个元素a1的存储地址用LOC(a1)表示 ,第i个数据元素ai的地址用LOC(ai)表示,则: 第i个数据元素的地址为: LOC(ai)=LOC(a1)+(i-1)×K (1≤i≤n)
数据结构第二章-2
2.5.2
L A
双向循环链表的存储
L B … Y Z ∧
图2.5.3 双向循环链表(循环至第一个数据结点 )及空表
采用循环链表并不额外增加空间,只是利用了原来 的空链域。这种循环办法有时能方便程序设计,提 高运算效率,减少参数传递。
current->nlink == L->first;//判断指针指向链表的最后一个结点 current == L->first;//判断指针指向链表的第一个结点 如从给定的结点指针p0处开始访问其后的第k个结点,则搜 寻的过程为: current = p0 ->nlink; int index=1; while (current!=p0 && index < k) { current = current ->nlink; index++; };
关键字→
姓 名
性别
政治面貌
职称
辅助关键字 男 姓↓ 名
女
共产党 民主党 无党派 教授 副教授 讲师
助教 ∧
教辅
黄强 男 民主党 教授 ∧
李永 男 无党派 ∧ 讲师
周明 男 ∧ 民主党 ∧ 讲师 ∧
张玉 女 共产党 副教授 ∧
赵志 ∧ 女 ∧ 共产党 ∧ 教辅 ∧
图2.7.2 多重链表的共享结构
2.8 链表应用
2.8.1
结点移至表首运算
实际应用中,一个数据被使用过后,可能下 次还会再次优先使用(如输入汉字 )。 对链表中被查找过的结点先从链表中删除 (删除后不释放),再插入到链表的表首 (或指定位置)。
q Lfirst × a b
× c
× d
current
数据结构的第二讲
数组基本概念
数组是可索引的数据的集合。
数据既可以是内置的类型,也可以是用户自定 义的类型。 事实上,把数组数据称为对象大概是最简便的 方式。 C#语言中的数组实际上就是对象本身,因为 它们都来源于 System.Array类。既然数组是 System.Array类的一个声明实例,所以在使用 数组时也可以使用此类的所有方法和属性。
一个数值 一个单独的索引
尽管常常是基于存储在数组行中的数值或者是基于存 储在数组列中的数值进行计算,但是对多维数组上所 有元素的计算还是很常见的操作。
一个例子
假设有一个 Grades数组,且数组的每一行是 一条学生记录,那么就能如下所示计算出每个 学生的平均成绩
参数数组
大多数的方法定义要求一套提供给方法的参数 的数目,但是想要编写一个允许可选参数数目 的方法定义是需要时间的。 可以采用一种称为参数数组的构造。
线性表的抽象数据类型定义
(3)ClearList(&L) 操作前提:线性表L已存在 。 操作结果:将表L置为空表。 (4)EmptyList(L) 操作前提:线性表L已存在。 操作结果:如果L为空表则返回真,否则返回假。 (5)ListLength(L) 操作前提:线性表L已存在。 操作结果:如果L为空表则返回0,否则返回表中的元素个数。 (6)Locate(L,e) 操作前提: 表L已存在,e为合法元素值。 操作结果: 如果L中存在元素e,则将“当前指针”指向元素e所在位置 并返回真,否则返回假。
锯齿状数组的声明
锯齿状数组的声明需要通过在数组变量名后放 置两组方括号的方式来完成 int[][] jagged = new int[12][]; 第一组方括号说明了数组的行数 第二组方括号则是留白的
数据结构课件ppt第二章
答:由于顺序存储结构一旦确定了起始位置, 线性表中的任何一个元素都可以进行随机存 取,即存取速度较高;并且,由于线性表的 总数基本稳定,且很少进行插入和删除,故 这一特点恰好避开了顺序存储结构的缺点。 因此,应选用顺序存储结构。
3. 在单链表和双向链表中,能否从当前结点 出发访问到任一结点?
• 答:在单链表中只能由当前结点访问其后 继的任一结点,但因其没有指向前驱的指 针而无法访问其前驱结点。在双向链表中, 由于当前结点既有指向后继的指针,又有 指向前驱的指针,所以在双向链表中可以 由当前结点出发访问表中的任何一个结点。
data 0
1
a2
2
a1
3
4
a3
cursor 2 4 1
0
data 0
1
a2
2
a1
3
a4
4
a3
cursor 2 3 1
4 0
…
…
…
…
maxsize-1
maxsize-1
静态链表的C语言描述
//线性表的静态链表存储结构 # define MAXSIZE 100 //链表的最大长度 typedef struct {
D. 循环链表
答案:C,D
A,C,D
写出带头结点的双向循环链表L为空表的 条件:
空表 L
答案:(L==L->next)&&(L==L->prior)
判断题
1. 在具有头结点的链式存储结构中,头指针 指向链表中的数据结点。( )
2. 顺序存储的线性表可以随机存取。( ) 3. 在单链表中,要访问某个结点,只要知道
} DuLNode, *DuLinkList;
2. 循环链表
3. 在单链表和双向链表中,能否从当前结点 出发访问到任一结点?
• 答:在单链表中只能由当前结点访问其后 继的任一结点,但因其没有指向前驱的指 针而无法访问其前驱结点。在双向链表中, 由于当前结点既有指向后继的指针,又有 指向前驱的指针,所以在双向链表中可以 由当前结点出发访问表中的任何一个结点。
data 0
1
a2
2
a1
3
4
a3
cursor 2 4 1
0
data 0
1
a2
2
a1
3
a4
4
a3
cursor 2 3 1
4 0
…
…
…
…
maxsize-1
maxsize-1
静态链表的C语言描述
//线性表的静态链表存储结构 # define MAXSIZE 100 //链表的最大长度 typedef struct {
D. 循环链表
答案:C,D
A,C,D
写出带头结点的双向循环链表L为空表的 条件:
空表 L
答案:(L==L->next)&&(L==L->prior)
判断题
1. 在具有头结点的链式存储结构中,头指针 指向链表中的数据结点。( )
2. 顺序存储的线性表可以随机存取。( ) 3. 在单链表中,要访问某个结点,只要知道
} DuLNode, *DuLinkList;
2. 循环链表
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
例1:两个矩阵相乘 for(I=1,I<=n;++I) for(j=1;j<=n;++j) { c[I][j]=0; for(k=1;k<=n;++k) c[I][j]+=a[I][k]*b[k][j];
}
• 由于是一个三重循环,每个循环从1到n,则总 次数为: n×n×n=n3 • 时间复杂度为T(n)=O(n3)
void select_sort(int a[], int n) { // 将 a 中整数序列重新排列成自小至大有序的整数序 列。 for ( i = 0; i< n-1; ++i ) { j = i; for ( k = i+1; k < n; ++k ) if (a[k] < a[j] ) j = k; if ( j != i ) a[j] ←→ a[i] n } // select_sort 基本操作: 比较(数据元素 数据元素)操作 基本操作 比较 数据元素 操作 时间复杂度: 时间复杂度 O(n2)
2)抽象数据类型的特点
由用户定义,用以表示应用问题的数据模型 由基本的数据类型组成, 并包括一组相关的服务(或 称操作) 数据抽象:用ADT描述程序处理的实体时,强调的是其本 质的特征,其所能完成的功能以及它和外部用户的借口。 信息隐蔽和数据封装,使用与实现相分离 并且对外部 用户隐藏其内部实现细节 抽象数据类型是模块化的思想的发展,它为模块的划 分提供了理论依据。
第一章 绪论
第二讲
了解抽象数据类型的定义与表示 理解算法特性、了解算法描述方法 理解算法特性、 掌握描述算法的类C 掌握描述算法的类C语言 掌握算法分析方法
2.抽象数据类型
1)抽象数据类型(Abstract Data Type 简称为ADT)可以看作是定 定 义了一组操作的一个抽象模型。 义了一组操作的一个抽象模型。 例如,集合与集合的并、交、差运算就可义为一个的抽象数 据类型。 一个抽象数据类型要包括哪些操作,这一点由设计者根据需要确 定。 例如,对于集合,如果需要,也可以把判别一个集合是否空 集或两个集合是否相等作为集合上的操作
1.4.3 算法效率的度量
• 对一个算法要作出全面的分析可分成两个阶段进 行,即事先分析和事后测试 事后测试 收集此算法的执行时间和实际占用空间 的统计资料。(有缺陷) 事先分析 求出该算法的一个时间界限函数 程序在计算机上运行时所消耗的时间取决的因素 ⑴硬件的速度。 ⑵书写程序的语言。 ⑶编译程序所生成目标代码的质量。 ⑷问题的规模。
• 频度:是指该语句重复执行的次数
• 例2 {++x;s=0;} • 将x自增看成是基本操作,则语句频度为1, 即时间复杂度为O(1) • 如果将s=0也看成是基本操作,则语句频度为 2,其时间复杂度仍为O(1),即常量阶。 • 例3、for(I=1;I<=n;++I) • {++x;s+=x;} • 语句频度为:2n 其时间复杂度为:O(n) • 即时间复杂度为线性阶。
初始条件:z1,z2 是复数。 操作结果:用sum返回两个复数z1,z2的和值。
} ADT Complex
•
• P9
1.3 抽象数据类型的表示和实现
一、算法
1. 算法举例 A、B、C三个整数的排序问题
例1
算法1: 1)比较A、B,将大数放入B中,小数放入A中; 2)比较B、C,将大数放入C中,小数放入B中; 3)再比较A、B,将大数放入B中,小数放入A中; 4)得A、B、C三者的升序结果。
• 一个算法是由控制结构 原操作 控制结构和原操作 控制结构 原操作构成的,其执行 时间取决于两者的综合效果。为了便于比较同一 问题的不同的算法,通常的做法 通常的做法是:从算法中选 通常的做法 取一种对于所研究的问题来说是基本运算的原操 作,以该原操作重复执行的次数作为算法的时间 度量。 • 一个算法的执行时间可以看成是所有原操作的执 行时间之和 ∑( 原操作(i)的执行次数×原操作(i)的执行 时间 )
• 语句频度为: • 1+2+3+…+n-2=(1+n-2) ×(n-2)/2 • =(n-1)(n-2)/2 • =n2-3n+2 • ∴时间复杂度为O(n2) • 即此算法的时间复杂度为平方阶. • 一个算法时间为O(1)的算法,它的基本运 算执行的次数是固定的。因此,总的时间由一 个常数(即零次多项式)来限界。而一个时间 为O(n2)的算法则由一个二次多项式来限界。
•
• 以下六种计算算法时间的多项式是最常 用的。其关系为: • O(1)<O(logn)<O(n)<O(nlogn) • <O(n2)<O(n3) • 指数时间的关系为: • O(2n)<O(n!)<O(nn) • 当n取得很大时,指数时间算法和多项 式时间算法在所需时间上非常悬殊。因 此,只要有人能将现有指数时间算法中 的任何一个算法化简为多项式时间算法, 那就取得了一个伟大的成就。
算法2:
1)比较A、B、C,将最大数放入C中; 2)再比较A、B,将大数放入B中,小数放入A中; 3)得A、B、C三者的升序结果。
例2
求两个正整数 m,n 中的最大数MAX的算法 (1)若 m > n 则 max=m (2)若 m <= n 则 max=n
小结: 小结:
1)算法就是解题过程的精确描述,具体来说就是用计算能够理解 的语言描述的解题过程。 2)将它作用于所求解的问题的给定输入集上,或作用于问题自身 的描述上,将产生唯一确定的动作序列,此序列是有限的;此序列 或终止于给出问题的解,或终止于指出问题对此输入无解。 3)算法由有限条可完全机械执行的,有确切含义的指令(或命令, 语句)构成。
• (2)可读性(Readability) 算法主要是为了人的阅读与交 流,其次才是为计算机执行。因此算法应该易于人的 理解;另一方面,晦涩难读的程序易于隐藏较多错误 而难以调试。 (3)健状性(Robustness) 当输入的数据非法时,算法应当 恰当地作出反映或进行相应处理,而不是产生莫名奇 妙的输出结果。并且,处理出错的方法不应是中断程 序的执行,而应是返回一个表示错误或错误性质的值。 (4)效率与存储量需求 效率指的是算法执行的时间;存 储量需求指算法执行过程中所需要的最大存储空间。 一般,这两者与问题的规模有关。 •
• 显然,在各种因素都不能确定的情况下, 很难比较出算法的执行时间。也就是说, 使用执行算法的绝对时间来衡量算法的效 率是不合适的。为此,可以将上述各种与 计算机相关的软、硬件因素都确定下来, 这样一个特定算法的运行工作量的大小就 一个特定算法的运行工作量的大小就 只依赖于问题的规模( 通常用正整数n 只依赖于问题的规模 ( 通常用正整数 n 表 或者说它是问题规模的函数。 示),或者说它是问题规模的函数。
• 抽象数据类型的形式描述为: ADT = ( D,S,P ) 其中:D 是数据对象, S 是 D 上的关系集, P 是 D 的基本操作集。 • ADT 抽象数据类型名 { 数据对象: 数据对象的定义 数据关系: 数据关系的定义 基本操作: 基本操作的定义 } ADT 抽象数据类型名 – 基本操作的 定义格式为: 定义格式为: – 基本操作名(参数表) 基本操作名(参数表) – 初始条件: 初始条件描述 初始条件描述>。 初始条件:<初始条件描述 。描述了操作执行之前 数据结构和参数应满足的条件,若不满足, 数据结构和参数应满足的条件,若不满足,则操作失 并返回相应出错信息。 败,并返回相应出错信息。
初始条件:复数已存在。 操作结果:复数Z被销毁。
GetReal( Z, &realPart )
初始条件:复数已存在。 操作结果:用 realPart 返回复数Z的实部值。
GetImag( Z, &ImagPart )
初始条件:复数已存在。 操作结果:用 ImagPart 返回复数Z的虚部值。
Add( z1,z2, &sum )
– 操作结果: 操作结果描述 操作结果描述>。说明了操作正常完成之后, 操作结果:<操作结果描述 。说明了操作正常完成之后, 数据结构的变化状况和应返回的结果。 数据结构的变化状况和应返回的结果。
• 若初始条件为空,则省略之。 若初始条件为空,则省略之。
例:抽象数据类型"复数"的定义
• ADT Complex {
• 4)输入 一个算法有零个或多个输入,这些输入取自于某个特定 的对象集合。 • 5)输出 一个算法有一个或多个输出,这些输出是同输入有着某 些特定关系的量。这种关系即算法的功能。 • 1.4.2 算法设计的要求 • 评价一个好的算法有以下几个标准: • (1) 正确性(Correctness ) 算法应满足具体问题的需求。即算法应 当满足以特定的“规格说明”方式给出的需求 其次,对算法是否“正确”的理解可以有以下四个层次: a.程序中不含语法错误; b.程序对于几组输入数据能够得出满足要求的结果; c.程序对于精心选择的、典型、苛刻切带有刁难性的几组输入数 据能够得出满足要求的结果; d.程序对于一切合法的输入数据都能得出满足要求的结果; 通常以第 c 层意义的正确性作为衡量一个算法是否合格的标准。
• 从算法中选取一种对于所研究的问题来说是基本操作的原操作,以该 基本操作在算法中重复执行的次数作为算法运行时间的衡量准则。 • 算法的之行时间和原操作的执行次数成正比
• 这种衡量效率的办法所得出的不是时间量,而是 一种增长趋势的量度。
• 一般情况下,算法中基本操作重复执行的次数是问题 规模n的某个函数,算法的时间量度记作T(n)=O(f(n))。 称作算法的渐近时间复杂度 渐近时间复杂度。 渐近时间复杂度 • 如果存在一个函数f(n), 存在一个常数k,一个起点n0, 当n≥n0 时恒有T(n)≤k*f(n)则T(n)被函数f(n)控制,于 是称这个算法的复杂度T(n)=O(f(n)),简称时间复杂度 O(f(n))。
}
• 由于是一个三重循环,每个循环从1到n,则总 次数为: n×n×n=n3 • 时间复杂度为T(n)=O(n3)
void select_sort(int a[], int n) { // 将 a 中整数序列重新排列成自小至大有序的整数序 列。 for ( i = 0; i< n-1; ++i ) { j = i; for ( k = i+1; k < n; ++k ) if (a[k] < a[j] ) j = k; if ( j != i ) a[j] ←→ a[i] n } // select_sort 基本操作: 比较(数据元素 数据元素)操作 基本操作 比较 数据元素 操作 时间复杂度: 时间复杂度 O(n2)
2)抽象数据类型的特点
由用户定义,用以表示应用问题的数据模型 由基本的数据类型组成, 并包括一组相关的服务(或 称操作) 数据抽象:用ADT描述程序处理的实体时,强调的是其本 质的特征,其所能完成的功能以及它和外部用户的借口。 信息隐蔽和数据封装,使用与实现相分离 并且对外部 用户隐藏其内部实现细节 抽象数据类型是模块化的思想的发展,它为模块的划 分提供了理论依据。
第一章 绪论
第二讲
了解抽象数据类型的定义与表示 理解算法特性、了解算法描述方法 理解算法特性、 掌握描述算法的类C 掌握描述算法的类C语言 掌握算法分析方法
2.抽象数据类型
1)抽象数据类型(Abstract Data Type 简称为ADT)可以看作是定 定 义了一组操作的一个抽象模型。 义了一组操作的一个抽象模型。 例如,集合与集合的并、交、差运算就可义为一个的抽象数 据类型。 一个抽象数据类型要包括哪些操作,这一点由设计者根据需要确 定。 例如,对于集合,如果需要,也可以把判别一个集合是否空 集或两个集合是否相等作为集合上的操作
1.4.3 算法效率的度量
• 对一个算法要作出全面的分析可分成两个阶段进 行,即事先分析和事后测试 事后测试 收集此算法的执行时间和实际占用空间 的统计资料。(有缺陷) 事先分析 求出该算法的一个时间界限函数 程序在计算机上运行时所消耗的时间取决的因素 ⑴硬件的速度。 ⑵书写程序的语言。 ⑶编译程序所生成目标代码的质量。 ⑷问题的规模。
• 频度:是指该语句重复执行的次数
• 例2 {++x;s=0;} • 将x自增看成是基本操作,则语句频度为1, 即时间复杂度为O(1) • 如果将s=0也看成是基本操作,则语句频度为 2,其时间复杂度仍为O(1),即常量阶。 • 例3、for(I=1;I<=n;++I) • {++x;s+=x;} • 语句频度为:2n 其时间复杂度为:O(n) • 即时间复杂度为线性阶。
初始条件:z1,z2 是复数。 操作结果:用sum返回两个复数z1,z2的和值。
} ADT Complex
•
• P9
1.3 抽象数据类型的表示和实现
一、算法
1. 算法举例 A、B、C三个整数的排序问题
例1
算法1: 1)比较A、B,将大数放入B中,小数放入A中; 2)比较B、C,将大数放入C中,小数放入B中; 3)再比较A、B,将大数放入B中,小数放入A中; 4)得A、B、C三者的升序结果。
• 一个算法是由控制结构 原操作 控制结构和原操作 控制结构 原操作构成的,其执行 时间取决于两者的综合效果。为了便于比较同一 问题的不同的算法,通常的做法 通常的做法是:从算法中选 通常的做法 取一种对于所研究的问题来说是基本运算的原操 作,以该原操作重复执行的次数作为算法的时间 度量。 • 一个算法的执行时间可以看成是所有原操作的执 行时间之和 ∑( 原操作(i)的执行次数×原操作(i)的执行 时间 )
• 语句频度为: • 1+2+3+…+n-2=(1+n-2) ×(n-2)/2 • =(n-1)(n-2)/2 • =n2-3n+2 • ∴时间复杂度为O(n2) • 即此算法的时间复杂度为平方阶. • 一个算法时间为O(1)的算法,它的基本运 算执行的次数是固定的。因此,总的时间由一 个常数(即零次多项式)来限界。而一个时间 为O(n2)的算法则由一个二次多项式来限界。
•
• 以下六种计算算法时间的多项式是最常 用的。其关系为: • O(1)<O(logn)<O(n)<O(nlogn) • <O(n2)<O(n3) • 指数时间的关系为: • O(2n)<O(n!)<O(nn) • 当n取得很大时,指数时间算法和多项 式时间算法在所需时间上非常悬殊。因 此,只要有人能将现有指数时间算法中 的任何一个算法化简为多项式时间算法, 那就取得了一个伟大的成就。
算法2:
1)比较A、B、C,将最大数放入C中; 2)再比较A、B,将大数放入B中,小数放入A中; 3)得A、B、C三者的升序结果。
例2
求两个正整数 m,n 中的最大数MAX的算法 (1)若 m > n 则 max=m (2)若 m <= n 则 max=n
小结: 小结:
1)算法就是解题过程的精确描述,具体来说就是用计算能够理解 的语言描述的解题过程。 2)将它作用于所求解的问题的给定输入集上,或作用于问题自身 的描述上,将产生唯一确定的动作序列,此序列是有限的;此序列 或终止于给出问题的解,或终止于指出问题对此输入无解。 3)算法由有限条可完全机械执行的,有确切含义的指令(或命令, 语句)构成。
• (2)可读性(Readability) 算法主要是为了人的阅读与交 流,其次才是为计算机执行。因此算法应该易于人的 理解;另一方面,晦涩难读的程序易于隐藏较多错误 而难以调试。 (3)健状性(Robustness) 当输入的数据非法时,算法应当 恰当地作出反映或进行相应处理,而不是产生莫名奇 妙的输出结果。并且,处理出错的方法不应是中断程 序的执行,而应是返回一个表示错误或错误性质的值。 (4)效率与存储量需求 效率指的是算法执行的时间;存 储量需求指算法执行过程中所需要的最大存储空间。 一般,这两者与问题的规模有关。 •
• 显然,在各种因素都不能确定的情况下, 很难比较出算法的执行时间。也就是说, 使用执行算法的绝对时间来衡量算法的效 率是不合适的。为此,可以将上述各种与 计算机相关的软、硬件因素都确定下来, 这样一个特定算法的运行工作量的大小就 一个特定算法的运行工作量的大小就 只依赖于问题的规模( 通常用正整数n 只依赖于问题的规模 ( 通常用正整数 n 表 或者说它是问题规模的函数。 示),或者说它是问题规模的函数。
• 抽象数据类型的形式描述为: ADT = ( D,S,P ) 其中:D 是数据对象, S 是 D 上的关系集, P 是 D 的基本操作集。 • ADT 抽象数据类型名 { 数据对象: 数据对象的定义 数据关系: 数据关系的定义 基本操作: 基本操作的定义 } ADT 抽象数据类型名 – 基本操作的 定义格式为: 定义格式为: – 基本操作名(参数表) 基本操作名(参数表) – 初始条件: 初始条件描述 初始条件描述>。 初始条件:<初始条件描述 。描述了操作执行之前 数据结构和参数应满足的条件,若不满足, 数据结构和参数应满足的条件,若不满足,则操作失 并返回相应出错信息。 败,并返回相应出错信息。
初始条件:复数已存在。 操作结果:复数Z被销毁。
GetReal( Z, &realPart )
初始条件:复数已存在。 操作结果:用 realPart 返回复数Z的实部值。
GetImag( Z, &ImagPart )
初始条件:复数已存在。 操作结果:用 ImagPart 返回复数Z的虚部值。
Add( z1,z2, &sum )
– 操作结果: 操作结果描述 操作结果描述>。说明了操作正常完成之后, 操作结果:<操作结果描述 。说明了操作正常完成之后, 数据结构的变化状况和应返回的结果。 数据结构的变化状况和应返回的结果。
• 若初始条件为空,则省略之。 若初始条件为空,则省略之。
例:抽象数据类型"复数"的定义
• ADT Complex {
• 4)输入 一个算法有零个或多个输入,这些输入取自于某个特定 的对象集合。 • 5)输出 一个算法有一个或多个输出,这些输出是同输入有着某 些特定关系的量。这种关系即算法的功能。 • 1.4.2 算法设计的要求 • 评价一个好的算法有以下几个标准: • (1) 正确性(Correctness ) 算法应满足具体问题的需求。即算法应 当满足以特定的“规格说明”方式给出的需求 其次,对算法是否“正确”的理解可以有以下四个层次: a.程序中不含语法错误; b.程序对于几组输入数据能够得出满足要求的结果; c.程序对于精心选择的、典型、苛刻切带有刁难性的几组输入数 据能够得出满足要求的结果; d.程序对于一切合法的输入数据都能得出满足要求的结果; 通常以第 c 层意义的正确性作为衡量一个算法是否合格的标准。
• 从算法中选取一种对于所研究的问题来说是基本操作的原操作,以该 基本操作在算法中重复执行的次数作为算法运行时间的衡量准则。 • 算法的之行时间和原操作的执行次数成正比
• 这种衡量效率的办法所得出的不是时间量,而是 一种增长趋势的量度。
• 一般情况下,算法中基本操作重复执行的次数是问题 规模n的某个函数,算法的时间量度记作T(n)=O(f(n))。 称作算法的渐近时间复杂度 渐近时间复杂度。 渐近时间复杂度 • 如果存在一个函数f(n), 存在一个常数k,一个起点n0, 当n≥n0 时恒有T(n)≤k*f(n)则T(n)被函数f(n)控制,于 是称这个算法的复杂度T(n)=O(f(n)),简称时间复杂度 O(f(n))。