1、计算机软件基础,教材及参考书,数据结构使用C语言西安交通大学出版社朱战立 数据结构( C语言版)清华大学出版社严蔚敏,吴伟民,学时安排,授课34+上机22,考核形式: (总分100分)考勤情况:5%(旷课一次扣0.5分,迟到两次扣0.5分) 平时作业:5%(A 5分,B 4分,C 3分,D 2分) 上机(包括操作和实验报告):20% 期末考试(闭卷笔试) :70%,上机:在微机上即可。安装C/C+的编译程序。使用Borland C+ 或 Visual C+ 都可以。但同一个源程序在这两个编译器上可能会出现不同的编译信息。,数据结构课程的地位,是介于数学、计算机硬件和计算机软件三者之间的一门核心
2、课程,1.1 数据结构的基本概念,为什么学习数据结构,数值计算,数学模型选择计算机语言编出程序测试最终解答。 数值计算的关键是:如何得出数学模型(方程)? 程序设计人员比较关注程序设计的技巧。,非数值计算,数据元素之间的相互关系一般无法用数学方程加以描述,描述客观事物的数字、字符以及一切能够输入到计算机中,并且能够被计算机程序处理的符号的集合。,表示一个事物的一组数据,是数据的基本单位,又称结点。在计算机程序中通常作为一个整体进行处理。一个数据元素由若干数据项构成。,数据元素之间具有的关系,即数据的组织形式。,具有相同性质的数据元素组成的集合。,基本概念,表结构,学籍登记表,学校机构组成,树结
3、构,交通图,图结构,非数值计算问题的数学模型不再是数学方程,而是诸如表、树和图之类的数据结构。,数据结构课程研究的是计算机所处理的数据元素间的结构关系及其操作实现的算法,1. 研究数据元素之间的客观联系。,2. 研究具有某种逻辑关系的数据在计算机存储器内的存储方式。,3. 研究如何在数据的各种结构(逻辑的和物理的)的基础上对数据实施一系列有效的基本操作。,算法,数据结构:计算机处理的数据元素的组织形式及其相互间的关系。由数据元素的有限集合及所有数据元素之间的关系组成。记为:Data_Structure = D, R其中,D是数据元素的有限集,R是 所有数据元素之间的关系的有限集合。,根据数据元
4、素间关系的基本特性,有四种基本数据结构 集合结构 数据元素间除“同属于一个集合”外,无其它关系线性结构 一个对一个,如线性表、栈、队列树形结构 一个对多个,如树图状结构 多个对多个,如图,集合结构,数据结构: SET =(K,R)K = 01,02,03,04,05,06,07,08,09,10 R = ,线性结构,数据结构 LINEARITY =(K,R)K = 01,02,03,04,05,06,07,08,09,10 R = , , ,数据元素之间的联系:1:1,树结构,数据结构 TREE =(K,R) K = 01,02,03,04,05,06,07,08,09,10 R = , ,数
5、据之间的联系:1:N,Graph = ( D, R ) D = 1,2,3,4,5,6,7,8,9 R = ,图结构,数据之间的联系: M:N,存储结构(Storage Structure):数据在计算机中的表示(或称映象)称为数据的存储结构,又称为物理结构。 四种基本的存储方法: (1)顺序存储方法(顺序存储结构) (2)链接存储方法(链式存储结构) (3)索引存储方法 (4)散列存储方法 同一种逻辑结构可采用不同的存储方法(以上四种之一或组合),这主要考虑的是运算方便及算法的时空要求。,顺序存储结构:用数据元素在存储器中的相对位置来表示数据元素之间的逻辑关系。链式存储结构:在每一个数据元素
6、中增加一个存放地址的指针,用此指针来表示数据元素之间的逻辑关系。,数据的逻辑结构,数据的存储结构,数据的运算,线性结构,非线性结构,顺序存储,链式存储,线性表,堆栈,队列,树形结构,图形结构,数据结构的三个方面:,散列存储,索引存储,串及数组,查找、排序、插入、删除、修改等,1.3 算法和算法分析,(2). 算法是由人们组织起来准备加以实施的一系列有限的基本步骤。,文字形式,程序设计语言形式(如C语言等),伪码形式,一个完整的算法应该满足下面五个基本标准:,输入性 有0个或多个输入 输出性 有一个或多个输出(处理结果) 确定性 每步定义都是确切、无歧义的 有穷性 算法应在执行有穷步后结束;整个
7、指令序列在有限的时间内完成。 可行性(有效性) 算法中的每一个步骤都应当能被有效的执行,并得到确定的结果。例如:被零除的计算动作是不能被有效执行的。,正确性 可读性 健壮性 高时间效率 高空间效率,当时间效率目标和空间效率目标发生矛盾时,应先考虑时间效率目标,时间复杂度 T(n) 空间复杂度 S(n) 其它(如可读性、可移植性等),前提条件:算法必须正确,2. 源程序编译的强弱以及所产生的机器代码 质量的优劣。,3. 机器执行一条指令的时间长短。,4. 程序中语句的执行次数。,1. 问题的规模。,一个程序在计算机中运行时间的多少与诸多因素有关,其中主要有:,称为时间频度, 记为T(n),定义:
8、若有一辅助函数f(n),当n趋于无穷大时,T(n)/f(n) 为一不等于零的实常数,则f(n)为T(n)的同数量级函数,记为 T(n)=O(f(n)称O(f(n)为时间复杂度。,例: 3n+2=O(n) /* 3n+24n for n2 */ 10n2+4n+2=O(n2) /* 10n2+4n+211n2 for n5 */ 6*2n+n2=O(2n) /* 6*2n+n2 7*2n for n4 */,常用的计算规则:,1.加法规则T(n) = T1(n)+ T2(n) = O(f1(n) + O(f2(n)= O(max(f1(n), f2(n),2. 乘法规则T(n) = T1(n)T
9、2(n) = O(f1(n) O(f2(n)= O(f1(n)f2(n),时间复杂度T(n)按数量级递增顺序为:,注 空间复杂度S(n)按数量级递增顺序也与上表类同。,复杂度高,复杂度低,时间复杂度的计算:,例1:,+x;s=0;,2,O(1),for(i=1;i=n;+i) +x;s+=x;,n+2n,O(n),for(j=1;j=n;+j) for(k=1;k=n;+k) +x;s+=x;,2n+2n2,O(n2),例2:,例3:,频度,时间复杂度,程序,例4:,频度,时间复杂度,程序,x=n;/n1 while(x=(y+1)*(y+1) y+;,n1/2-1,O(n1/2),例5:,x
10、=91; y=100; while(y0) if(x100) x=x-10;y-; else x+;,常数,O(1),例6:,频度,时间复杂度,程序,O(n3),int i,j,k,x=0; for(i=1;i=n; i+)for(j=1;j=i; j+)for(k=1;k=j; k+)x=x+2;,按增长率由小至大的顺序排列下列各函数:2100,(3/2)n,(2/3)n,nn ,n0.5 ,n! ,2n ,lgn ,nlgn,n3/2,思路: 先将题中的函数分成如下几类: 常数阶:2100 对数阶:lgn K次方阶:n0.5、n3/2 指数阶 (按指数由小到大排):nlgn、(3/2)n、
11、2n、 n!、 nn (2/3)n 2100 lgn n0.5 n3/2 nlgn (3/2)n 2n n! nn,1、数据结构是指计算机处理的 的组织形式以及它们相互之间的 。 A.数据元素 B.计算方法C.逻辑存储 D.数据映像 A.结构 B.关系C.运算 D.算法,课 堂 练 习,3、衡量算法好坏的两个主要指标有算法的 和 。,时间复杂度,空间复杂度,2、数据结构研究数据的 、 和操作实现算法。A.结构关系、组织形式B.逻辑结构、物理结构C.数据元素、数据对象D.数据复杂性、程序复杂性,4、下面程序段的时间复杂度是 。i=s=0;while(sn)i+;s+=i;,O(n),5、算法的时
12、间复杂度仅与问题的规模有关。 ( ),* 还与输入的元素取值有关,6、下面程序段Aij=0执行次数为 , 时间复杂度为 。for(i=1;i=n;i+)for(j=1;j=i;j+)Aij=0;,n(n+1)/2,O(n2),理解:数据,数据元素,数据项,数据结构。特别是数据结构的逻辑结构、存储结构及数据运算的含义及其相互关系。数据结构的两大类逻辑结构和四种常用的存储表示方法。掌握:算法、算法的时间复杂度和空间复杂度、最坏的和平均时间复杂度等概念,对一般算法要能分析出时间复杂度。,作业:P25 1-1,1-2,13,17,1-11,小 结,END,复习: C语言的数据类型,1、基本数据类型,i
13、nt short; long; unsigned float float; double; long double,2、指针类型,1000,3,i_pointer,i,地址(i的指针),指针变量,1000,*i_pointer,i,1000,15,i=3;,3,int i;,指针变量的定义int i;int *i_pointer;i_pointer=,i=3;,* i_pointer=3;,5,main() int x=5;printf(“n%d”,x);Function1(x);printf(“n%d”,x) void Function1(int x) x+;printf(“n%d”,x);
14、 ,main() int x=5;printf(“n%d”,x);Function1( ,值传送,地址传送,x,5,x,6,x,5,1000,px,1000,*px,6,3. 数组类型,数组名就是数组的起始地址 数组作为函数参数时,为地址传递,int a100;,a &a0, a+1 &a1,*a a0, *(a+1) a1,4、字符串,字符串定义成字符数组0为字符串结束标志,char a40=“I am a student”;,strlen(a) 为14 不包括0,5. 结构体类型,结构体由若干个结构体成员组成。 定义结构体类型变量: 1.定义结构体类型; 2.定义结构体类型变量。,stru
15、ct student char name10;int age;float score; ; struct student student1; struct student stu2100; struct student *p;,6. 自定义类型,typedef char elemtype; typedef struct student char name10;int age;float score; stu; elemtype a; stu student1;,具有独立含义的最小标识单位,是数据的最小单位,数据元素,数据项,逻辑结构,a1 a2 a3 a30,存储结构,1. 顺序存储结构,线性
16、结构(线性表),2. 链式存储结构,百钱买百鸡问题: 100元钱买100只鸡,母鸡每只5元,公鸡每只3元,小鸡3只1元,问共可以买多少只母鸡、多少只公鸡、多少只小鸡?,for (i=0; i=100; i+)for (j=0; j=100; j+)for (k=0; k=100;k+) if (k%3=0 ,求解:设母鸡、公鸡、小鸡各为i,j,k只,则有:i+j+k=1005i+3j+k/3=100只需要解出本方程就可以得到答案。 方法1:用三重循环,方法2、3:用两重循环 因总共买100只鸡,所以小鸡的数目可以由母鸡数和公鸡数得到。,for ( i=0;i100;i+)for (j=0;j1
17、00;j+) k=100-i-j ;if (k%3=0 ,for (i=0;i=20;i+)for (j=0;j33;j+) k=100-i-j ;if (k%3=0 ,方法4:用一重循环 由i+j+k=100和5*i+3*j+k/3=100合并为一个方程: 14*i+8*j=200, 简化: 7*i+4*j=100得: i不超过14,i必为4的倍数?!,for ( i=0; i=14; i+=4 ) j = (100-7*i)/4;k=100-i-j;printf(“%d,%d,%dn”, i,j,k); ,上面四个方法中,第一个方法的循环次数为:100*100*100,一百万次;第二个方法
18、的循环次数为:100*100,1万次;第三个方法为:20*34,680次;第四个方法为:4次. 由此可见,算法的设计至关重要。,BACK,第二章 线性表,Chapter 2 Linear List,数据结构课程涉及数学、计算机硬件和计算机软件 数据结构定义指互相有关联的数据元素的集合,用D_S=( D, R ) 或 S=( D, R) 表示。 数据结构内容数据的逻辑结构、存储结构和运算 算法效率指标时间效率和空间效率,要点回顾,逻辑结构唯一,存储结构不唯一,运算的实现依赖于存储结构,线性表的逻辑结构 线性表的顺序存储结构 线性表的链式存储结构(单链表) 应用实例,本章内容,若结构是非空有限集,
19、则有且仅有一个开始结点和一个终端结点,并且所有结点都最多只有一个直接前趋和一个直接后继。,可表示为:(a0 , a1 , , an-1),线性结构的定义:,线性结构的特点:, 只有一个首结点和一个尾结点; 除首尾结点外,其他结点只有一个直接前驱和一个直接后继。,线性结构包括线性表、堆栈、队列、字符串、数组等等,其中,最典型最常用的是-,( a0 , a1 ai-1,ai, ai1 ,, an-1),2.1 线性表的逻辑结构,1. 线性表的定义:用数据元素的有限序列表示,n=0时称为,数据元素,线性起点 (首结点),ai的直接前趋,ai的直接后继,下标,是元素的序号,表示元素在表中的位置,空表,
20、线性终点 (尾结点),n为元素总个数,即表长,例1 分析26 个英文字母组成的英文表,( A, B, C, D, , Z),例2 分析学生情况登记表,每个数据元素由5个数据项组成; 元素之间的关系是线性的,数据元素都是字母; 元素之间的关系是线性的,同一线性表中的元素必定具有相同特性,2. 线性表的基本操作 Initiate(L) 初始化操作。建立一个空线性表L。 Length(L) 求表长。求给定线性表L中数据元素的个数。 Get(L,i) 读取元素。读取线性表L中第i个数据元素。 Insert(L,i,x) 前插。在线性表L中第i个数据元素ai之前插入一个新的数据元素x。 Delete(L
21、,i) 删除。删除线性表L中第i个的数据元素ai。 Locate(L,x) 定位函数。返回线性表L中元素值等于x的数据元素ai的序号i。,2.2 线性表的顺序存储结构顺序表,一、顺序表用一组地址连续的存储单元存储线性表的各个数据元素,称作线性表的顺序存储结构,简称顺序表。,顺序表的特点: 1. 逻辑上相邻的数据元素,其物理上也相邻; 2. 若已知表中首元素在存储器中的位置,则其他元素存放位置亦可求出(利用数组下标,参见存储结构示意图)。,线性表的顺序存储结构示意图,每个元素 占K字节,一个一维数组,下标的范围是到,每个数组元素用相邻的个字节存储。存储器按字节编址,设存储数组元素的第一个字节的地
22、址是98,则的第一个字节的地址是,113,例1:,因此:LOC( M3 ) = 98 + 5 3=113,解:地址计算通式为:,LOC(ai) = LOC(a0) + L *i,用c语言定义顺序表,#define Maxlen 100 typedef struct char name10;char sex;int age; elemtype; elemtype ListMaxlen; int num=-1;,/*定义数据类型*/,/*定义顺序表*/,/*当前数据元素下标*/,/*顺序表最大长度*/,typedef struct elemtype ListMaxlen;int num; SeqL
23、ist;,s-num,s-List0,s-List1,s-List2,s-ListMaxlen-1,SeqList a; SeqList *s;,a.num, a.List0,用c语言定义顺序表,二、顺序表的基本操作,1.初始化 ListInitiate(L),void ListInitiate(SeqList *L) L-num=-1;,/*num指示线性表最后一个元素的下标*/,2.求表长 ListLength(L),int ListLength(SeqList L) return L.num+1; ,3.取数据元素 ListGet(L,i,x),int ListGet(SeqList L
24、,int i,elemtype *x) if(iL.num) printf(“ERROR!n”);return 0; else *x=L.Listi;return 1; ,x,4. 插入(在第i个(0=i=n)数据元素之前插入一个新的数据元素x),i位置非法?,开始,n-1至i位置的 元素依次后移,N,Y,N,Y,前插算法流程图,是否满足0inum+1,num Maxlen-1是否成立,for(j=num;j=i;j-)aj+1=aj;,ai=x;,num+;,注意:n表示数据元素的个数,num是线性表最后一个元素的下标,增强健壮性,int ListInsert(SeqList *L, int
25、 i, elemtype x) int j;if( iL-num+1 ) printf(“errorn”); return 0; if (L-num)=Maxlen-1) printf(“overflown”); return 0; for(j=L-num;j=i;j-)L-listj+1L-Listj;L-Listix; L-numL-num+1;return 1; ,判断i是否合法,判断表是否已满,若i合法,元素后移,将元素x存放在i位置,当前数据元素下标加1,用c语言描述插入算法,该算法的时间复杂度:,Eis: 插入一个元素所需平均移动次数: 则 因此, 该算法的时间复杂度为O(n)。,
26、5.删除(删除第i个(0=i=n-1)数据元素),删除算法流程图,位置非法?,N,Y,表空?,Y,for(j=i+1;j=num;j+)aj-1=aj;,num-;,判断num0是否成立,是否满足0i num,N,用c语言描述删除算法,int ListDelete (SeqList *L, int i, elemtype *x) int j;if(L-numL-num) printf (“n the position is invalid”);return 0; else *x=L-listi; for ( j=i+1; jnum; j+) L-listj-1=L-listj;L-num-;r
27、eturn 1; ,/*删除顺序表L中的第i个元素,并将其保存在x中*/,/*判断表是否为空*/,/*若i合法,元素依次前移*/,/*当前数据元素下标减1*/,/*判断i值是否合法*/,该算法的时间复杂度:,Edl:删除一个元素所需平均移动次数因此, 该算法的时间复杂度为O(n)。,算法时间主要耗费在移动元素的操作上,因此计算时间复杂度的基本操作(最深层语句频度) T(n)= O (移动元素次数) 移动元素的个数取决于插入或删除元素的位置.,顺序表时间效率分析:,顺序表的空间复杂度S(n)=O(1) (没有占用辅助空间),顺序表空间效率分析:,三、顺序存储结构的特点,顺序表的优点: 无需为表示
28、节点间的逻辑关系而增加额外的存储空间 可以方便地随机存取表中的任一节点 顺序表的缺点: 插入和删除运算不方便,需要移动大量的数据元素。 由于要求占用连续的存储空间,存储分配只能预先进行,作业:P55 2-8 2-14(顺序表),如何克服顺序表的这些缺点呢?,第二章 线性表,线性结构的特点:仅有一个首、尾结点,其余元素仅有一个直接前驱和一个直接后继。,2. 线性表,逻辑结构:“一对一” 或 1:1存储结构:顺序存储、链式存储,3.顺序表,特征:逻辑上相邻,物理上一定相邻 优点:随机查找快 缺点:插入、删除慢;需要预先知道线性表的长度,单链表基本概念单链表基本操作,线性表的链式存储结构链表,单链表
29、的基本概念,线性表链式存储结构的一种。用一组不一定连续的存储单元来存放数据元素。,数据域,指针域,结点,头指针,空指针,a0,1475,130A,a1,10CB,1475,a2,10CB,数据元素的逻辑顺序是通过链表中的指针连接次序来实现的。,结点,数据域,指针域,typedef struct Node DataType data; struct Node *next; SLNode;,2.3.1 单链表的存储结构,Loc(a1),Loc(a2),Loc(an-1),Loc(a0),逻辑示意图,物理示意图,head ,链表结构示意图,带头结点的单链表,带头结点的空单链表,head-next=N
30、ULL,不带头结点的单链表,不带头结点的空单链表,head=NULL,头指针,头结点,首元结点,何谓头指针、头结点和首元结点?,头指针是指向链表中第一个结点(或为头结点或为首元结点)的指针。单链表可由一个头指针唯一确定。 头结点是在链表的首元结点之前附设的一个结点;数据域内只放空表标志和表长等信息; 首元结点是指链表中存储线性表第一个数据元素a0的结点。,首元结点,a0,一个线性表的逻辑结构为:(ZHAO,QIAN,SUN,LI,ZHOU,WU,ZHENG,WANG),其存储结构用单链表表示如下,请问其头指针的值是多少?,例:,答:头指针是指向链表中第一个结点的指针,因此关键是要寻找第一个结点
31、的地址。,31,头指针的值是31,上例链表的逻辑结构示意图有以下两种形式:,区别: 无头结点 有头结点,相关知识,动态内存分配,设计人员根据具体问题的具体需要,在程序运行时再具体确定数组的个数或占用内存单元的大小,从而在程序运行时具体确定所需要的内存单元空间。,malloc()函数,free()函数,头文件 malloc.h,# include ,malloc()函数,free()函数,函数原型: void * malloc ( unsigned size),函数功能: 用于向系统动态申请size个字节的内存单元空间,函数返回值为所申请的内存空间首地址。,函数原型: void free ( v
32、oid * p),函数功能:用于释放动态分配的内存空间。,sizeof 运算符:,sizeof(已定义的数据类型),功能:返回括号中给出的已定义数据类型占用的字节个数。,Memory Allocation,如:sizeof(int),例如:定义结构体类型typedef struct nodetype int data;struct nodetype *next;SLNode;,p=( SLNode * ) malloc(sizeof(SLNode) );,SLNode *p; p=malloc(sizeof(SLNode);,强制类型转换,(1)指针后移操作p=p-next,1475,(2)指
33、向指针的指针SLNode *h;,130A,*h,*h,1000,h,1000,一级指针,二级指针,int ListInitiate( SLNode *head ) if(*head=(SLNode* )malloc(sizeof(SLNode)=NULL) return 0;(*head) - next=NULL;return 1; ,(1)初始化,2.3.2 单链表的操作实现,12EF,head,*head,NULL,main() SLNode * h;ListInitiate ( ,头结点,12EF,(2)求当前数据元素个数,int ListLength(SLNode *head) SL
34、Node *p=head;int size=0;while(p-next!=NULL) p=p-next;size+; return size; ,(3) 取元素(寻找到第i个结点ai并返回该结点的数据元素), p=p-next;j+; ,while(p-next!=NULL&ji),*x=p-data;,int ListGet(SLNode *head, int i,DataType *x) SLNode *p;int j=0;phead; while(p-next!=NULL) ,/*找第i个结点*/,/*判断是否找到该结点*/,/*将数据元素值赋给*x*/,步骤:(1)找插入位置,指针p
35、指向ai的前一个结点(2)插入:1、x结点指针域指向ai结点 2、ai-1结点的指针域指向x结点,(2),(2.1),(2.2),(4)插入运算(前插,即在ai之前插入一个数据元素x),不可以!,(2.1)和(2.2)可不可以交换?为什么?,?,p=p-next;j+; ,while(p-next!=NULL&ji-1),x,p-next=s;,1614,10CB,s-next=p-next;,s-data=x;,s=(SLNode * )malloc(sizeof(SLNode);,int ListInsert(SLNode *head, int i, DataType x) SLNode
36、*p, *s;int j;p=head;j=-1;while(p-next!=NULL),用c语言实现的单链表插入算法,定义变量 并初始化,搜索表,寻找ai-1结点,if(j!=i-1) printf(“n插入位置不合理!”);return 0; if (s=(SLNode * )malloc(sizeof(SLNode)=NULL)return 0; s-data=x; s-next=p-next; p-next=s; return 1; ,插入位置不合理,判断是否申请到新结点,将该结点插入到ai结点之前,(5)单链表的删除(删除第i(i=0)个结点),1500,s=p-next;,p-ne
37、xt=s-next;,free(s);, p=p-next;j+; ,while(p-next!=NULL&p-next-next!=NULL&ji-1),ListDelete (SLNode *head, int i, DataType *x) SLNode *p,*s;int j;p=head; j=0; while(p-next!=NULL ,用c语言实现的单链表删除算法,定义变量 并初始化,搜索表,寻找ai-1结点,if(j != i-1) printf(“n 删除位置不合理!”);return 0; s = p-next;*x=s-data;p-next =p-next -next;
38、free(s);return 1; ,删除位置不合理,将ai结点删除,释放s结点空间,关于上机的相关说明,1、实验报告不得有雷同,否则按不及格处理;,2、函数自己编写,函数名、变量名等自己定义;,#include #define MAXLEN 100 typedef int datatype; typedef structdatatype ListMAXLEN;int num; Seqlist; 函数声明,void main() 变量定义printf(“选择所要进行的操作:1:初始化n2:插入n3:删除n4:输出n5:退出n“);scanf(%d”,default:给出出错信息,并要求重新输入
39、 ,(6) 单链表的创建 尾接法,130A,1475,for(j=0;jdata=aj;s-next=NULL;p-next=s;p=s;,开始,N,Y,尾接法创建单链表流程图,int CreatL1(SLNode *h,DataType a,int n) SLNode *p,*s;int i,j;i=ListInitiate(h);if (i=0) return 0;p=*h;for(j=0;jdata=aj;s-next=NULL;p-next=s;p=s; return 1; ,a0,NULL,130A,a1,130A,1475,for(j=0;jdata=aj; s-next=(*h)
40、-next; (*h)-next=s; ,(6) 单链表的创建头插法,开始,N,Y,头接法创建单链表流程图,int CreatL2(SLNode *h,DataType a,int n) SLNode *s;int i,j;i=ListInitiate(h);if (i=0) return 0; for(j=0;jdata=aj;s-next=(*h)-next;(*h)-next=s; return 1; ,2.3.5 循环单链表,非空表,空表,head-next=head,2.3.6双向循环链表,typedef struct Node DataType data;struct Node *
41、prior,*next; DLNode;,要点回顾,线性表的链式存储链表,单链表结点,数据域,指针域,单链表的初始化、插入、删除、头插法及尾插法创建单链表,讨 论,线性表逻辑结构特点是,只有一个首结点和尾结点;除首尾结点外其他结点只有一个直接前驱和一个直接后继。简言之,线性结构反映结点间的逻辑关系是一对一(1:1)的。,问1:线性表的逻辑结构特点是什么?其顺序存储结构和链式存储结构的特点是什么?,答:,顺序存储时,相邻数据元素的存放地址也相邻(逻辑与物理统一);要求内存中可用存储单元的地址必须是连续的。,链式存储时,相邻数据元素可随意存放,但所占存储空间分两部分,一部分存放结点值,另一部分存放
42、表示结点间关系的指针。,顺序存储的优点是存储密度大(1),存储空间利用率高。缺点是插入或删除元素时不方便。链式存储的优点是插入或删除元素时很方便,使用灵活。缺点是存储密度小(1),存储空间利用率低。,答:,问2:顺序存储和链式存储各有哪些优缺点?,事实上,链表插入、删除运算的快捷是以空间代价来换取时间。,问3:在什么情况下用顺序表比链表好?,顺序表适宜于做查找这样的静态操作;链表宜于做插入、删除这样的动态操作。 若线性表的长度变化不大,且其主要操作是查找,则采用顺序表; 若线性表的长度变化较大,且其主要操作是插入、删除操作,则采用链表。,答:,应用实例1,删除顺序表la中所有值为x的数据元素。
43、设顺序表的数据结构定义为:,#define MAX 100 typedef int DataType; typedef struct DataType ListMAX;int num; /*最后一个数据元素的下标*/ SeqList;,void DeleteSeqList ( SeqList *la , DataType x ) int j, k ;for (j=0; jnum; j+ ) if (la-List j=x) for (k=j ;knum;k+)la-List k=la-List k+1;la-num-; j- - ; ,应用实例2,删除顺序表a中第i(i=0)个元素起的k个元素
44、。,#define MAX 100 typedef int DataType; typedef struct DataType ListMAX;int num;/*最后一个数据元素的下标*/SeqList;,int DeleteK(SeqList *a,int i,int k) int j; if(a-numa-num) return 0;else for(j=i;jnum-k;j+) a-Listj=a-Listj+k; a-num= a-num-k;return 1; ,/*判断表是否为空*/,/*判断删除位置、个数是否合理*/,/*删除从第i个元素开始的k个元素*/,应用实例3,在有序顺
45、序表中插入值为x的数据元素以保持顺序表的有序性。,#define MAX 100 typedef int DataType; typedef struct DataType ListMAX;int num;/*最后一个数据元素的下标*/SeqList;,int Orderlnsert (SeqList *L , DataType x ) int i ;if (L-num=Max-1) printf (“ 顺序表已满”); return 0;else for (i=L-num; i=0 ,应用实例4,实现单链表的就地逆序。设其头结点的指针为head,编写一个算法将单链表逆置。,单链表的逆转,p,
46、q,q,q,p,p,p,void reverse(SLNode *head) SLNode *p,*q;p = head-next;head-next = NULL;while (p!= NULL) q= p;p = p-next;q-next = head-next;head-next = q; ,应用实例5,已知线性表la和lb中的数据元素按非递减有序排列,将la和lb表中的数据元素合并为一个新的线性表lc,lc中的数据元素仍按非递减有序排列,并要求不破坏la和lb表。,La = ( 3, 5, 8, 11 ) Lb=( 2, 6, 8, 9, 11, 15, 20 ) 合并结果: Lc
47、= ( 2, 3, 5, 6, 8, 8, 9, 11, 11, 15, 20 ),typedef struct elemtype Listmaxlen;int num; qltype;,1.顺序表结构,int mergeql(qltype la,qltype lb, qltype *lc) int i,j,k;if(la.num+1+lb.num+1maxlen) printf(“n数组下界溢出!”);return 0;i=j=k=0;while(i=la.num&j=lb.num) if(la.listi=lb.listj),lc-listk+=la.listi+; elselc-listk+=lb.listj+; while(ilistk+=la.listi+; while(jlistk+=lb.listj+; lc-num=k-1; return 1; ,