数据结构

Download Report

Transcript 数据结构

111071
数据结构
课程综述
周菁
[email protected]
计算机学院
1
111071
数据结构
课程内容
数据结构主要研究:
• 数据的逻辑结构 (集合、线性、树和图),
• 数据在计算机中的存储结构 (顺序、链接、索引和散
列),以及
• 对数据进行各种非数值运算的方法 (包括查找、排序、
插入、删除、修改和遍历)和算法。
对同样的数据,若采用的逻辑结构和存储结构不同,
对某一运算所采用的方法不同,将得到不同的算法,
在计算机上会有不同的运行时间和存储空间效率。
2
111071
数据结构
课程目的
通过对数据结构课程的学习,我们应该能够
·根据实际应用中对数据处理的要求,为数据选
择和建立合适的逻辑和存储结构;
·选择和使用较好的数据处理方法;
·利用一种程序设计语言编写出相应的算法;
·在计算机系统上调试、运行和实现算法。
3
111071
数据结构
课程安排
• 教材:《数据结构(C语言版)》,严蔚敏、吴伟
民编著,清华大学出版社
• 授课时间:
第1-16周,周三3、4节
(一教504)
单周四5、6节 (一教513)
双周四5、6节 (48教B101东)
4
111071
数据结构
课程安排
• 考核方式:
课堂出勤、平时作业、测试与上机占30%,
期末考试占70%
5
111071
数据结构
课程结构
第一部分:数据结构的基本概念(第1章)
第二部分:基本的数据结构,包括:
线性结构——线性表、栈和队列、数组与广义表(第2~
5章)
非线性结构——树、图(第6~7章)
第三部分:基本技术,包括:查找技术与排序技
术(第9~10章)
6
第一章 绪论
1.1 什么是数据结构
1.2 基本概念和术语
1.3 抽象数据类型的表示与实现
1.4 算法和算法分析
1.4.1 算法
1.4.2 算法设计的要求
1.4.3 算法效率的度量
1.4.4 算法的存储空间需求
周菁
数据结构A(111071)
7
1.1 什么是数据结构
例1 电话号码查询系统
假设有一个电话号码薄,它记录了n个人
的名字和其相应的电话号码,其形式如下:
(a1,b1) (a2,b2) … (an,bn)
其中ai,bi(i=1,2…n) 分别表示某人的名
字和对应的电话号码。要求设计一个算法,
当给定任何一个人名时,该算法能够打印出
此人的电话号码,如果该电话簿中没有这个
人,则该算法能够报错。
周菁
数据结构A(111071)
8
要解此问题首先构造一张电话号码登记表。表中每个
结点(元素)存放两个数据项:姓名和电话号码。写出
好的查找算法,取决于这张表的结构及存储方式。
最简单的方式是将表中结点(元素)顺序地存储在计
算机中。查找时从头开始依次查对姓名,直到找出正
确的姓名或是找遍整个表均没有找到为止。
这种查找算法对于一个不大的单
位或许是可行的,但对一个有成
千上万私人电话的城市就不实用
了。
周菁
数据结构A(111071)
9
若这张表是按姓氏排列的,则可另造一张姓氏索引表,
采用如图所示的存储结构:
那么查找过程是先在索引表中查对姓氏,然后根据索引
表中的地址到电话号码登记表中核查姓名,这样查找登
记表时就无需查找其它姓氏的名字了。因此,在这种新
的结构上产生的查找算法就更为有效。
周菁
数据结构A(111071)
10
例1-1 图书馆的书目检索系统自动化问题
例1-2 计算机和人对弈问题
例1-3 多叉路口交通灯的管理问题
通过以上几例可以直接地认为:数据结构就是
研究数据的逻辑结构和物理结构以及它们之间相互
关系,并对这种结构定义相应的运算,而且确保经
过这些运算后所得到的新结构仍然是原来的结构类
型。
周菁
数据结构A(111071)
11
第一章 绪论
1.1 什么是数据结构
1.2 基本概念和术语
1.3 抽象数据类型的表示与实现
1.4 算法和算法分析
1.4.1 算法
1.4.2 算法设计的要求
1.4.3 算法效率的度量
1.4.4 算法的存储空间需求
周菁
数据结构A(111071)
12
1.2 基本概念和术语
数据(data)是对客观事物的符号表示。在计算机
科学中是指所有能输入到计算机中并被计算
机程序处理的符号的总称。
数据元素(data element)是数据的基本单位,在计
算机程序中通常作为一个整体进行考虑和处
理。一个数据元素可由若干个数据项组成。
数据项是数据的不可分割的最小单位。
周菁
数据结构A(111071)
13
数据对象(data object):是性质相同的数据元素的
集合,是数据的一个子集。
数据结构(data structure):是相互之间存在一种或
多种特定关系的数据元素的集合,数据结构主
要指逻辑结构和物理结构。
周菁
数据结构A(111071)
14
逻辑结构是指数据元素之间的逻辑关系,通常分为
四类基本结构:
1.
集合:结构中的数据元素除了同属于一种类型外,
别无其他关系。
2.
线性结构:结构中的数据元素之间存在一对一的
关系。
3.
树型结构:结构中的数据元素之间存在一对多的
关系。
4.
图状结构或网状结构:结构中的数据元素之间存
在多对多的关系。
周菁
数据结构A(111071)
15
数据结构的形式定义为:数据结构是一个二元组
Data_Structure = (D,S),
其中:D是数据元素的有限集,S是D上关系的有限集。
例1-4 复数的数据结构定义如下:
Complex = (C,R)
其中:C是含两个实数的集合{c1,c2},分别
表示复数的实部和虚部。R = {P},P是定义在集合
C上的一种关系{〈c1,c2〉}。
周菁
数据结构A(111071)
16
物理结构是指数据结构在计算机中的表示(映像),
又称为存储结构。
数据结构在计算机中有两种不同的表示方法:顺序表
示和非顺序表示,由此得出两种不同的存储结构:
– 顺序存储结构:用数据元素在存储器中的相对
位置来表示数据元素之间的逻辑关系。(p.6)
– 链式存储结构:在每一个数据元素中增加一个
存放地址的指针,用此指针来表示数据元素之
间的逻辑关系。 (p.6)
周菁
数据结构A(111071)
17
数据类型是一个值的集合和定义在这个值集上的一组
操作的总称。
高级程序语言中数据类型可以分为:
– 原子类型:属非结构类型,其值不可分解
– 结构类型:其值由若干成分按某种结构组成的,
可以分解
例2 在C语言中数据类型:
原子类型:整型、实型、字符型、指针、枚举型
结构类型:数组、结构、联合
周菁
数据结构A(111071)
18
抽象数据类型(abstract data type,简称ADT)是指一个
数学模型以及定义在该模型上的一组操作。
抽象数据类型的定义仅取决于它的一组逻辑特性,
而与其在计算机内部如何表示和实现无关,只要
其数学特性不变,就不影响其外部的使用。
抽象数据类型的定义由一个值域和定义在该值域上的
一组操作组成,可用三元组描述如下:(D, S, P),
其中,D是数据对象,S是D上的关系集,P是对D
的基本操作。
周菁
数据结构A(111071)
19
第一章 绪论
1.1 什么是数据结构
1.2 基本概念和术语
1.3 抽象数据类型的表示与实现
1.4 算法和算法分析
1.4.1 算法
1.4.2 算法设计的要求
1.4.3 算法效率的度量
1.4.4 算法的存储空间需求
周菁
数据结构A(111071)
20
1.3 抽象数据类型的表示与实现
我们采用下述格式定义一个ADT:
ADT ADT名 {
数据对象: <数据对象的定义>
数据关系: <数据关系的定义>
基本操作: <基本操作的定义>
}ADT ADT名
其中,数据对象和数据关系用伪码描述,基本操作的定义格
式为
基本操作名(参数表)
初始条件: <初始条件描述>
操作结果: <操作结果描述>
周菁
数据结构A(111071)
21
例1-6 抽象数据类型三元组的定义:
ADT Triplet {
数据对象:D = {e1, e2, e3 | e1, e2, e3属于
Elemset(定义了关系运算的某个集合)}
数据关系:R1 = {<e1, e2>,<e2, e3>}
基本操作:
InitTriplet(&T, v1, v2, v3)
初始条件:
操作结果: 构造三元组T,元素e1, e2和e3分
别被赋予参数v1, v2和v3的值。
周菁
数据结构A(111071)
22
DestroyTriplet(&T)
初始条件: 三元组T已经存在。
操作结果: 销毁三元组T。
Get(T, i, &e)
初始条件: 三元组T已经存在,1<=i<=3。
操作结果: 用e返回三元组T的第i个元素。
Put(&T, i, e)
初始条件: 三元组T已经存在,1<=i<=3。
操作结果: 用e值取代三元组T的第i个元素。
IsAscending(T)
初始条件: 三元组T已经存在。
操作结果: 如果三元组T的三个元素按升
序排列,则返回TRUE,否则返回FALSE。
周菁
数据结构A(111071)
23
IsDescending(T)
初始条件: 三元组T已经存在。
操作结果: 如果三元组T的三个元素按降
序排列,则返回TRUE,否则返回FALSE。
Max(T, &e)
初始条件: 三元组T已经存在,。
操作结果: 用e返回三元组T的最大值。
Min(T, &e)
初始条件: 三元组T已经存在,。
操作结果: 用e返回三元组T的最小值。
}ADT Triplet
周菁
数据结构A(111071)
24
类C语言
1. 预定义常量和类型
// 函数结果状态代码
#define
#define
#define
#define
#define
#define
TRUE 1
FALSE 0
OK
1
ERROR 0
INFEASIBLE
OVERFLOW
-1
-2
//Status是函数的类型,其值是函数结果状态代码
typedef int Status;
周菁
数据结构A(111071)
25
类C语言
2. 数据结构的表示(存储结构)用类型定义
(typedef)描述。数据元素类型约定为
ElemType,由用户在使用该数据类型时自行定
义。例如:
typedef struct LNode {
ElemType
data;
struct LNode *next;
}LNode, *LinkList;
周菁
数据结构A(111071)
26
类C语言
3. 基本操作的算法都用以下形式的函数描述:
函数类型 函数名(函数参数表){
//算法说明
语句序列
} // 函数名
– 函数的参数需要说明类型,辅助变量可以不作说明,必
要时对其作用给予注释;
– 一般而言,a、b、c、d、e用作数据元素名,i、j、k、l、
m、n用作整型变量,p、q、r用作指针变量名;
– 增添了C++的引用调用的参数传递方式,在形参表中,
&打头的参数即为引用参数
周菁
数据结构A(111071)
27
第一章 绪论
1.1 什么是数据结构
1.2 基本概念和术语
1.3 抽象数据类型的表示与实现
1.4 算法和算法分析
1.4.1 算法
1.4.2 算法设计的要求
1.4.3 算法效率的度量
1.4.4 算法的存储空间需求
周菁
数据结构A(111071)
28
1.4 算法和算法分析
算法(algorithm)是对特定问题求解步骤的一种描述。算
法是指令的有限序列,其中每一条指令表示一个或
多个操作。
五个重要特性:
(1)有穷性:一个算法必须总是在执行有穷步之后结
束,且每一步都在有穷时间内完成。
(2)确定性:算法中每一条指令必须有确切的含义,
不存在二义性;且算法只有一个入口和一个出口。
周菁
数据结构A(111071)
29
(3)可行性:一个算法是可行的,即算法描述的操作
都是可以通过已经实现的基本运算执行有限次来实现
的。
(4)输入:一个算法有零个或多个输入,这些输入取
自于某个特定的对象集合。
(5)输出:一个算法有一个或多个输出,这些输出是
同输入有着某些特定关系的量。
周菁
数据结构A(111071)
30
算法描述
采用文字描述,则如下步骤所示:
① 给n个元素a1~an输入数值;
② 把第一个元素a1赋给用于保存
最大值元素的变量x;
③ 把表示下标的变量i赋初值2;
④ 如果i≤n则向下执行,否则输
出最大值x后结束算法;
⑤ 如果ai>x则将ai赋给x;
⑥ 将下标i增1,以指示下一个元
素;
⑦ 转向第④步继续执行。
开始
为n个元素a1~an输入数值
a1→x
2→i
N
i≤n
Y
ai>x
N
Y
ai→x
输出x
结束
i+1→i
求n个元素中的最大值
周菁
数据结构A(111071)
31
算
法
C
/* 程序1-1.c*/
#include<studio.h>
#define N 8
/* 定义N为整数8 */
void main(void) {
int i, x, a[N];
/* 用a[0]~a[N-1]保存a1~an元素 */
printf(“请输入%d个整数:”, N);
for (i=0; i < N; i ++)
scanf(“%d”, &a[i]);
x=a[0];
/* 把第一个元素a[0]的值赋给x */
i=1;
/* 把第二个元素a[1]的下标1赋给i */
while (i<N) {
/* 循环比较得到最大值 */
if (a[i] >x) x=a[i]; i ++;
}
printf(“%d个整数中的最大值为:%d\n”, N, x);
语
言
描
述
}
周菁
数据结构A(111071)
32
评价一个好的算法有以下几个标准:
(1) 正确性(correctness) 算法应满足具体问题的需求。
(2) 可读性(readability) 算法应该好读,以有利于阅读
者对程序的理解。
(3) 健壮性(robustness) 算法应具有容错处理。当输入
非法数据时,算法应对其作出反应,而不是产生莫名
其妙的输出结果。
(4) 效率与低存储量需求 效率指的是算法执行的时间;
存储量需求指算法执行过程中所需要的最大存储空间。
一般,这两者与问题的规模有关。
周菁
数据结构A(111071)
33
算法效率的度量
• 算法执行时间是通过依据该算法编制的程序在计算
机上运行时所消耗的时间来度量。
• 事后统计方法,使用计算机内部计时功能,其缺陷
是必须先运行程序,而且所得时间的统计量依赖于
计算机的环境因素。
• 事先分析估算方法,比较同一问题的不同算法,通
常的做法是以算法中基本操作重复执行的次数作
为算法的时间度量。
周菁
数据结构A(111071)
34
时间复杂度
一般情况下,算法中基本操作(如赋值、比较、计算、
转向、返回、输入、输出等)重复执行的次数是问
题规模 n 的某个函数,算法的时间量度记作
T (n)=O (f (n))
称作算法的渐近时间复杂度,简称时间复杂度。
周菁
数据结构A(111071)
35
时间复杂度
一个算法是由控制结构(顺序、分支和循环)和原操作(固
有数据类型的操作)构成,则算法时间取决与二者综合效果。
通常的做法是从算法中选取一种对于所研究问题来说是基本
操作的原操作,以该基本操作重复执行的次数作为算法的时
间度量。
多数情况下,被称做问题的基本操作的原操作是最深层循环内
的语句中的原操作,其执行次数和包含它的语句的频度(语句
重复执行次数)相同。
周菁
数据结构A(111071)
36
例如在以下矩阵相乘的算法中,“乘法”运算是该问题
中的基本操作,
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];
}
所以整个算法的执行时间记作
T(n) = O(n3)
*定义:若f (n)是正整数n的一个函数,则xn=O (f (n) )
表示存在一个正的常数M,使得当n≥n0,有
︱xn ︳≤M ︱ f (n) ︱ 。
周菁
数据结构A(111071)
37
例3 {++x; s=0; }
将x自增看成是基本操作,则语句频度为1,即
时间复杂度为O(1);如果将 s=0 也看成是基本
操作,则语句频度为2,其时间复杂度仍为O
(1),即常量阶。
例4 for (i=1; i≤n; ++i)
{++x; s+=x; }
基本操作的语句频度为2n, 其时间复杂度为O
(n),即时间复杂度为线性阶。
周菁
数据结构A(111071)
38
例5 for (i=1; i ≤ n; ++i)
for (j=1; j ≤ n; ++j)
{++x; s+=x; }
基本操作的语句频度为2n2, 其时间复杂度为
O(n2),即时间复杂度为平方阶。
定理:若A(n)=a m n m +a m-1 n m-1 +…+a1n+a0是一个
m次多项式,则A(n)=O (n m)。
证略。
周菁
数据结构A(111071)
39
例6 for (i=2; i ≤ n; ++i)
for (j=2; j ≤ i-1; ++j) {++x; a[i, j]=x;}
基本操作的语句频度为
1+2+3+…+n-2=(1+n-2)×(n-2)/2
=(n-1)(n-2)/2 =n2-3n+2
时间复杂度为O (n2),即此算法的时间复杂度为平方阶。
随着n值的增大,不同数量级对应的值的增长速度是不
一样的,它们之间存在以下关系:
O(log2n) < O(n)< O(nlog2n)<O(n2)<O(n3)<O(2n)<O(n!)
周菁
数据结构A(111071)
40
算法的时间复杂度的分类
• 算法的时间复杂度还可以分为最好、最差和平均三种
情况。下面结合从一维数组a[n]中查找等于给定值key的
元素的算法进行说明。
Status SequenceSearch(int a[], int n, int key) {
/* 若查找成功则返回元素下标值,否则返回-1 */
int i;
for (int i = 0; i<n; i++)
if (a[i] == key) return i;
return INFEASIBLE;
}
• 此算法的时间复杂度主要取决于for循环体中基本操作
的频度
周菁
数据结构A(111071)
41
算法的时间复杂度的分类
• 最好的情况是第一个元素a[0]的值等于key,相应的时
间复杂度为O (1); 最差的情况是最后一个元素a[n-1]的
值等于key,相应的时间复杂度为O (n); 平均情况是每
一个元素等于key都有相同的概率(即1/n),则查找成
功所需同元素进行比较的平均次数是(1/n) ∑i =
(1/2)(n+1),其中i = 1,2,…,n,相应的时间复杂度为O (n)。
• 平均情况的时间复杂度最有实际意义,因为它确切地
反映了运行一个算法的平均快慢速度。
周菁
数据结构A(111071)
42
空间复杂度
• 空间复杂度是对一个算法在运行过程中临时占用存储
空间大小的量度,记作:
S (n) = O (f (n))
其中n为问题的规模(或大小)。
• 评价算法的空间复杂度通常只考虑在运行过程中为局
部变量分配的存储空间的大小:
为参数表中形参变量分配的存储空间
为在函数体中定义的局部变量分配的存储空间
周菁
数据结构A(111071)
43
时间复杂度与空间复杂度
• 对于一个算法,其时间复杂度和空间复杂度往往是相
互影响。
• 算法的所有性能之间都存在或多或少的相互影响,设
计算法时要综合考虑算法的各项性能、算法的使用频
率、算法处理的数据量的大小、算法描述语言的特性、
算法运行的机器环境等各方面的因素。
周菁
数据结构A(111071)
44
复习题
1. 数据结构是一门研究程序设计中数据的  A 以
及它们之间的  B 和运算等的学科。
 A.元素
B.计算方法 C.逻辑存储 D.映像
 A.结构
B.关系
C.运算
D.算法
C
2. 在数据结构中,从逻辑上可以把数据结构分为__。
A.动态结构和静态结构 B.紧凑结构和非紧凑结构
C.线性结构和非线性结构 D.内部结构和外部结构
周菁
数据结构A(111071)
45
复习题
3. 在链式存储结构中,一个存储结点存储一个 B 。
A.数据项 B.数据元素 C.数据结构 D.数据类型
4. 数据运算的执行
A
。
A. 效率与采用何种存储结构有关
B. 是根据存储结构来定义的
C. 有算术运算和关系运算两大类
D. 必须用程序设计语言来描述
周菁
数据结构A(111071)
46
复习题
5. 数据采用链式存储结构时,要求
A
。
A. 每个结点占用一片连续的存储区域
B. 所有结点占用一片连续的存储区域
C. 结点的最后一个数据域是指针类型
D. 每个结点有多少个后继,就设多少个指针域
周菁
数据结构A(111071)
47
复习题
6. 以下说法中,不正确的是
D
。
A. 数据元素是数据的基本单位
B. 数据项是数据中不可分割的最小可标识单位
C. 数据可由若干个数据元素构成
D. 数据项可由若干个数据元素构成
周菁
数据结构A(111071)
48
复习题
7. 某算法的时间复杂度为O (n2),表明该算法
的 C
。
A. 问题的规模是n2
B. 执行时间等于n2
C. 执行时间与n2成正比
D. 问题规模与n2成正比
周菁
数据结构A(111071)
49
复习题
8. 以下为各算法所有语句频度之和的表示式,其中
时间复杂度相同的是 A、B 。
A. TA(n)=2n3+3n2+1000
B. TB(n)=n3-n2log2n-1000
C. TC(n)=n2log2n+n2
D. TD(n)=n2+1000
周菁
数据结构A(111071)
50
复习题
9. 判断以下说法是否正确。
1) 数据对象是一组数据元素的集合。(  )
2) 任何数据结构都具备三个基本运算:插入、删除
和查找。(  )
3) 数据的逻辑结构与各数据元素在计算机中如何存
储有关。 (  )
4) 数据的逻辑结构是指数据的各数据项之间的逻辑
关系。 (  )
周菁
数据结构A(111071)
51
复习题
5)算法可以用不同的语言描述,如果用C或PASCAL
等高级语言来描述,算法就等同于程序。(  )
6)数据结构、数据元素、数据项在计算机中的映像
(或表示)分别称为存储结构、结点结构和数据
域。 (  )
typedef struct LNode {
ElemType
data;
struct LNode *next;
}LNode, *LinkList;
周菁
数据结构A(111071)
52
复习题
10.求出下列算法的时间复杂度。
1) 比较同一简单类型的两个数据x1和x2的大小,对于
x1>x2,x1=x2和x1<x2这三种不同情况分别返回‘>’、
‘=’和‘<’字符。
char compare(SimpleType x1,SimpleType x2) {
if (x1>x2) return‘>’;
else if (x1==x2) return ‘=’;
else return‘<’;
}
其时间复杂度为O (1)。
周菁
数据结构A(111071)
53
复习题
2) 将一个字符串中的所有字符按相反方向的次序重新放
置。
void Reverse(char *p) {
int n=strlen(p);
for (int i=0; i<n/2; i++) {
char ch;
ch=p[i];
p[i]=p[n-i-1];
p[n-i-1]=ch;
}
}
其时间复杂度为O (n)。
周菁
数据结构A(111071)
54
复习题
3) 从二维整型数组a[m][n]中查找出最大元素所在的行、列下
标。
void Find(int a[M][N],int m,int n,int &Lin,int &Col) {
//M和N为全局常量,应满足M>=n和N>=n的条件,Lin和Col
为引用形参,它是对应实参的别名,其值由实参带回
Lin=0; Col=0;
for (int i=0;i<m;i++)
for (int j=0;j<n;j++)
if (a[i][j]>a[Lin][Col]) {
Lin=i; Col=j;
}
}
其时间复杂度为O (m*n)。
周菁
数据结构A(111071)
55
复习题
4) void func(int n) {
int y = 0;
while (y * y <=n)
y ++;
}
其时间复杂度为O (n1/2)。
周菁
数据结构A(111071)
56
复习题
5) void func(int n) {
int i, x = 0;
for (i = 1; i < n; i ++)
for (j=i+1; j <=n; j ++)
x++;
}
其时间复杂度为O (n2)。
周菁
数据结构A(111071)
57
复习题
6) void func(int n) {
int m = 0, i, j;
for (i = 1; i <= n; i ++)
for (j=2 * i; j <=n; j ++)
m++;
}
其时间复杂度为O (n2)。
周菁
数据结构A(111071)
58