1、,大家新年好!,杨平办公室:2412E-mail:,数据结构,教材: 数据结构教程(第3版) 李春葆 清华大学出版社 2009 (另配套学习指导和上机实验指导两书,作为参考)参考书: 1.数据结构(C语言版)严蔚敏,吴伟民 清华大学出版社 1997 2.实用数据结构基础 陈元春,中国铁道出版社,C语言 数据结构 软件工程,掌握基本编程方法,掌握数据组织和数据处理的方法,掌握大型软件开发方法,学习识字,学习写作文,学习写小说,基本要求,课程关系,与语文学习过程类比,动手能力(上机),前期课程,数据结构,计算机基础C语言离散数学,后期课程,操作系统编译原理数据库原理软件工程,承上启下,计算机科学课
2、程体系(偏软),课程安排,72课时118周最终成绩平时成绩40期末考试成绩60平时成绩包括:平时作业(准备作业本,纸张不批阅)、上课提问、期中考试、上机实验关于课表中“单周上机”说明:没有特殊声明,在多媒体教室上课。,第1章 绪论,1.2 算法及其描述,1.1 什么是数据结构,1.3 算法分析,本章小结,1.4 数据结构算法程序,1.1.1 数据结构的定义,1.1.2 逻辑结构类型,1.1.3 存储结构类型,1.1.4 数据结构和数据类型,1.1 什么是数据结构,数据:是所有能被输入到计算机中,且能被计算机处理的符号的集合。,数据元素:是数据(集合)中的一个“个体”,是数据的基本单位。,数据对
3、象:是具有相同性质的若干个数据元素的集合。 数据项:是数据不可分割的、具有独立意义的最小数据单位,是对数据元素属性的描述。也称为域,或字段。,例如:f080113班为一个学生数据对象,而其中的“张三”是一个数据元素。,1.1.1 数据结构的定义,数据结构:是指数据以及数据元素相互之间的联系。可以看作是相互之间存在着某种特定关系的数据元素的集合。 因此,可时把数据结构看成是带结构的数据元素的集合。,数据结构包括如下几个方面: (1) 数据元素之间的逻辑关系,即数据的逻辑结构。 (2) 数据元素及其关系在计算机存储器中的存储方式,即数据的存储结构,也称为数据的物理结构。 (3) 施加在该数据上的操
4、作,即数据的运算。,例1.1 学生表数据元素是学生记录,每个数据元素由四个数据项(即学号、姓别、性别和班号)组成。,该表中的记录顺序反映了数据元素之间的逻辑关系, 用学号标识每个学生记录,这种逻辑关系可以表示为: , 其中尖括号“”表示元素ai和ai+1之间是相邻的,即ai在ai+1之前,ai+1在ai之后。,数据在计算机存储器中的存储方式就是存储结构。 C/C+语言中,通常采用结构体数组和链表两种方式实现其存储结构。,存放学生表的结构体数组Stud定义为: struct int no; /*存储学号*/ char name8; /*存储姓名*/ char sex2; /*存储性别*/ cha
5、r class4; /*存储班号*/ Stud7=1,“张斌”,“男”,“9901”, 5,王萍,女,9901;,结构体数组Stud各元素在内存中顺序存放,即第i(1i6)个学生对应的元素Studi存放在第i+1个学生对应的元素Studi+1之前,Studi+1正好在Studi之后。,存放学生表的链表的结点类型StudType定义为: typedef struct studnode int no; /*存储学号*/ char name8; /*存储姓名*/ char sex2; /*存储性别*/ char class4; /*存储班号*/ struct studnode *next; /*存储
6、指向下一个学生的指针*/ StudType;,链表首结点地址head,1,张斌,男,9901,8,刘丽,女,9902,34,李英,女,9901,20,陈华,男,9902,12,王奇,男,9901,26,董强,男,9902,5,王萍,女,9901,学生表构成的链表如右图所示。其中的head为第一个数据元素的指针。,学生表构成的链表,(1) 数据结构通常是研究数据的( )及它们之间的相互联系。 A存储结构和逻辑结构 B存储和抽象 C联系和抽象 D联系与逻辑(2)链式存储的存储结构所占存储空间( )。 A 分两部分,一部分存放结点值,另一部分存放表示结点间关系的指针 B 只有一部分,存放结点值 C
7、只有一部分,存储表示结点间关系的指针 D分两部分,一部分存放结点值,另一部分存放结点所占单元素,小练习,为了更确切地描述一种数据结构,通常采用二元组表示: B=(K,R) 其中,B是一种数据结构,它由数据元素的集合K和K上二元关系的集合R所组成。,逻辑结构的描述或表示:,序偶(x,yK) x为第一结点,y为第二结点。 x为y的直接前驱结点(通常简称前驱结点) y为x的直接后继结点(通常简称后继结点)。 若某个结点没有前驱结点,则称该结点为开始结点;若某个结点没有后继结点,则称该结点为终端结点。,说明:表示有向关系,(x,y)表示无向关系。采用离散数学的表示方法。,例如,采用二元组表示例1.1的
8、学生表。 学生表中共有7个结点,依次用k1k7表示,则对应的二元组表示为B=(K,R),其中: K=k1,k2,k3,k4,k5,k6,k7 R=r /只有一种关系 r=,又例如,有如下数据即一个矩阵:,对应的二元组表示为B=(K,R),其中: K=2,6,3,1,8,12,7,4,5,10,9,11 R=r1,r2 其中,r1表示行关系,r2表示列关系 r1=, , r2=, , ,一个二维数组,(1) 线性结构 结点之间关系:一对一。 特点:开始结点和终端结点都是惟一的,除了开始结点和终端结点以外,其余结点都有且仅有一个前驱结点,有且仅有一个后继结点。顺序表就是典型的线性结构。,1.1.2
9、 逻辑结构类型,(2) 树形结构 结点之间关系:一对多。 特点:开始结点惟一,终端结点不惟一。除终端结点以外,每个结点有一个或多个后续结点;除开始结点外,每个结点有且仅有一个前驱结点。,(3) 图形结构 结点之间关系:多对多。 特点:没有开始结点和终端结点,所有结点都可能有多个前驱结点和多个后继结点。,学生表,井字棋对弈问题,城市连通网络,(2) 链式存储方法,(3) 索引存储方法,(4) 散列存储方法,(1) 顺序存储方法,1.1.3 存储结构类型P7,(1) 数据类型 高级程序语言中,一般须对程序中出现的每个变量、常量或表达式,明确说明它们所属的数据类型。不同类型的变量,其所能取的值的范围
10、不同,所能进行的操作不同。 数据类型是一个值的集合和定义在此集合上的一组操作的总称。,1.1.4 数据结构和数据类型,如C/C+中的int就是整型数据类型。它是所有整数的集合(在16位计算机中为3276832767的全体整数)和相关的整数运算(如、等)。,(2) 抽象数据类型 抽象数据类型(Abstract Data Type简写为ADT)指的是用户进行软件系统设计时从问题的数学模型中抽象出来的逻辑数据结构和逻辑数据结构上的运算,而不考虑计算机的具体存储结构和运算的具体实现算法。 抽象数据类型=数据元素集合抽象运算,例如,抽象数据类型复数的定义:ADT Complex 数据对象: D=e1,e
11、2|e1,e2均为实数数据关系: R1=| e1是复数的实数部分,e2 是复数的 虚数部分 ,e1e2i,基本操作: AssignComplex(&Z,v1,v2):构造复数Z。 DestroyComplex(&Z):复数Z被销毁。 GetReal(Z,&real):返回复数Z的实部值。 GetImag(Z,&Imag):返回复数Z的虚部值。 Add(z1,z2,&sum):返回两个复数z1,z2的和。 ADT Complex,1.2.1 什么是算法,1.2.2 算法描述,1.2 算法及其描述,数据元素之间的关系有逻辑关系和物理关系,对应的操作有逻辑结构上的操作功能和具体存储结构上的操作实现。
12、 通常把具体存储结构上的操作实现步骤或过程称为算法。,1.2.1 什么是算法,算法的五个重要的特性,(1) 有穷性:在有穷步之后结束。,(2) 确定性:无二义性。,(3) 可行性:可通过基本运算有限次执行来实现。,(4) 有输入,(5) 有输出,例 考虑下列两段描述:(1) 描述一void exam1() n2; while (n%20) nn+2; printf(%dn,n);,华中科大考研题,(2) 描述二void exam2() y=0; x=5/y; printf(“%d,%dn”,x,y); 这两段描述均不能满足算法的特征,试问它们违反了哪些特征?,解:(1)算法是一个死循环,违反了
13、算法的有穷性特征。 (2)算法包含除零错误,违反了算法的可行性特征。,本书中采用C/C+语言描述算法。 说明:C+语言中引用运算符“&”(别名)。 注意:Turbo C不支持引用类型。,1.2.2 算法描述,编写一个函数swap1(x,y),当执行语句swap1(a,b)时,交换a和b的值。 void swap1(int x,int y) int tmp; tmp=x;x=y;y=tmp; 注意:a和b的值不会发生了交换。,为此,采用指针的方式来回传形参的值,需将上述函数改为: void swap2(int *x,int *y) int tmp; tmp=*x;/*将x的值放在tmp中*/ *
14、x=*y; /*将x所指的值改为*y*/ *y=tmp; /*将y所指的值改为tmp*/ ,引入“引用”的概念例如: int a=4; /*a为普通的整型变量*/ int /*b是a的引用变量*/ 这里说明b变量是变量a的引用,b也等于4,之后这两个变量同步改变。当a改变时b也同步改变,同样,当b改变时a也同步改变。,难点,引用常用于函数形参中,采用引用型形参时,在函数调用时将形参的改变回传给实参 void swap(int y=tmp 当用执行语句swap(a,b)时,a和b的值发生了交换。,例1.3 编写一个算法, 读入三个整数x,y和z的值,要求从大到小输出这三个数。 解:依次输入x,y
15、和z这三个整数, 通过比较交换后,使得xyz, 然后输出x,y,z。 在算法中应考虑对这三个元素作尽可能少的比较和移动,如下述算法在最坏的情况下只需进行3次比较和7次移动。,void Descending() printf(输入x,y,z); scanf(%d,%d,%d,1.3.1 算法时间复杂度分析,1.3.2 算法空间复杂度分析,1.3 算法分析,同一问题可以采用多种算法实现。如何比较算法执行效率? 算法描述的语言不同 算法执行的环境不同 所以不能用绝对执行时间进行比较,1.3.1 算法时间复杂度分析,所以,通常把算法中包含基本运算次数的多少称为算法的时间复杂度,也就是说,一个算法的时间
16、复杂度是指该算法的基本运算次数。 算法中基本运算次数T(n)是问题规模n的某个函数f(n),记作: T(n)=O(f(n),算法执行时间大致为基本运算所需的时间与其运算次数(也称为频度)的乘积。,也就是只求出T(n)的最高阶,忽略其低阶项和常系数,这样既可简化T(n)的计算,又能比较客观地反映出当n很大时,算法的时间性能。 例如,T(n)=3n2-5n+10000=O(n2),本质上讲,是一种最高数量级的比较,一个没有循环的算法的基本运算次数与问题规模n无关,记作O(1),也称作常数阶。 一个只有一重循环的算法的基本运算次数与问题规模n的增长呈线性增大关系,记作O(n),也称线性阶。 其余常用
17、的还有平方阶O(n2)、立方阶O(n3)、对数阶O(log2n)、指数阶O(2n)等。,各种不同数量级对应的值存在着如下关系: O(1)O(log2n)O(n)O(n*log2n)O(n2)O(n3)O(2n)O(n!),求两个n阶方阵的相加C=A+B的算法如下,分析其时间复杂度。 #define MAX 20 /*定义最大的方阶*/ void matrixadd(int n,int AMAXMAX, int BMAXMAX,int CMAXMAX) int i,j; for (i=0;in;i+)for (j=0;jn;j+) Cij=Aij+Bij; ,例1.4,该算法中的基本运算是两重循
18、环中最深层的语句Cij=Aij+Bij,分析它的频度,即: T(n)= =O(n2),分析以下算法的时间复杂度。 int fun(int n) int i,j,k,s; s=0; for (i=0;i=n;i+) for (j=0;j=i;j+) for (k=0;k=j;k+) s+; return(s); ,基本语句或基本操作,例1.5,解:该算法的基本操作是语句s+,其频度: T(n)= =O(n3)则该算法的时间复杂度为O(n3)。,分析以下算法的时间复杂度。void func(int n) int i=0,s=0; while (sn) i+; s=s+i; ,基本语句,例1.6,解
19、:对于while循环语句,设执行的次数为m,i从0开始递增1,直到m为止,有: s=0+1+2+m-1=m(m-1)/2, 并满足s=m(m-1)/2n,则有m 。 T(n)=O( ) 所以,该算法的时间复杂度为O( )。,有如下算法: void fun(int a,int n,int k) /*数组a共有n个元素*/ int i;if (k=n-1) for (i=0;in;i+) printf(%dn,ai);else for (i=k;in;i+)ai=ai+i*i; fun(a,n,k+1); 调用上述算法的语句为fun(a,n,0),求其时间复杂度。,例1.7,解:设fun(a,n,
20、0)的时间复杂度为T(n),fun(a,n,k)的执行时间为T1(n,k),由fun()算法可知: T1(n,k)=n 当k=n-1时 T1(n,k)= (n-k)+T1(n,k+1) 其他情况 则 T(n)=T1(n,0)=n+T1(n,1)=n+(n-1)+T1(n,2)=n+(n-1)+2+T1(n,n-1)=n+(n-1)+ +2+n=O(n2) 所以调用fun(a,n,0)的时间复杂度为O(n2)。,空间复杂度是对一个算法在运行过程中临时占用的存储空间大小的量度,一般也作为问题规模n的函数,以数量级形式给出,记作: S(n) = O(g(n) 若所需额外空间相对于输入数据量来说是常数
21、,则称此算法为原地工作。若所需存储量依赖于特定的输入,则通常按最坏情况考虑。,返回,1.3.2 算法空间复杂度分析,例1.8 分析例1.4和例1.5的空间复杂度。 解:由于这两个算法中临时变量的个数与问题规模n无关,所以空间复杂度均为O(1)。,分析例1.7的空间复杂度。 解: fun(a,n,k)临时空间大小为S(k),S(k)=1 当k=n-1时S(k)=1+S(k+1) 其他情况调用fun(a,n,0)的空间复杂度为S(0)=1+S(1)=1+1+S(2)=1+1+S(n-1)=1+1+.+1=nO(n),练习,P24 25,数据结构对算法的影响主要在两方面 (1)数据结构的存储能力数据
22、结构存储能力强、存储信息多算法将会较好设计(时间少),存储空间大。时间和空间的平衡(2)定义在数据结构上的操作在数据结构上定义基本操作算法调用这些基本操作。,1.4 数据结构算法程序,选择数据结构需要考虑的几个方面:(1)数据结构要适应问题的状态描述(2)数据结构应与所选择的算法相适应(3)数据结构的选择同时要兼顾程序设计的方便(4)灵活应用已有知识,例如,有若干学生数据(学生数小于50),每个学生数据包含学号(每个学生学号是惟一的,但学生记录不一定按学号顺序存放)、姓名、班号和若干门课程成绩(每个学生所选课程数目可能不等,但最多不超过6门)。要求设计一个程序输出每个学生的学号、姓名和平均分以
23、及每门课程(课程编号从16)的平均分。,设计方案1:将学生的全部数据项放在一个表中,一个学生的全部数据对应一条记录。由于课程最多可选6门,对应的成绩项也应有6个。对应的数据结构如下:struct studint no;/*学号*/char name10;/*姓名*/int bno;/*班号*/int deg1;/*课程1分数*/int deg2;/*课程2分数*/int deg3;/*课程3分数*/int deg4;/*课程4分数*/int deg5;/*课程5分数*/int deg6;/*课程6分数*/;,特点:存储空间:中(若学生没有选该课程,对应空间仍存在)算法时间:少算法简洁性差:算法
24、完全依赖数据结构,P19,算法:求某个学生的平均分 求某门课程的平均分,设计方案2:将学生的全部数据项放在一个表中,但一个学生的一门课程成绩对应一条记录。这样成绩项只需要一个,为了区分不同课程成绩,需增加一个课程编号项。对应的数据结构如下:struct studint no;/*学号*/char name10;/*姓名*/int bno;/*班号*/int cno;/*课程编号*/int deg;/*课程分数*/;,特点:存储空间:大算法时间:多 P21算法简洁性:好,设计方案3:将学生的学号、姓名和班号放在一个表中,将成绩数据放在另一个表中,两者通过学号关联。前者一个学生对应一个记录,后者一
25、门课程成绩对应一条记录。对应的数据结构如下:struct stud1int no;/*学号*/char name10;/*姓名*/int bno;/*班号*/;struct stud2int no;/*学号*/int cno;/*课程编号*/int deg;/*分数*/;,特点:存储空间:少算法时间:中算法简洁性:好,数据结构,算法,数据类型,i,j,k,求解问题编写程序的代码:ijk种,优选,最佳方案,本课程的目标,本章小结 本章介绍了数据结构的基本概念,主要学习要点如下: (1) 数据结构的定义,数据结构包含的逻辑结构、存储结构和运算三方面的相互关系。 (2) 各种逻辑结构即线性结构、树形结构和图形结构之间的差别。,(3) 数据结构和数据类型的差别和联系。 (4) 算法的定义及其特性。 (5) 算法的时间复杂度和空间复杂度分析。,作业,P25 1.4(3)P26 实验题1.3,