




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1第十一章 链表2例:跳马。依下图将每一步跳马之后的位置例:跳马。依下图将每一步跳马之后的位置(x,y)(x,y)放放到一个到一个“结点结点”里,再用里,再用“链子穿起来链子穿起来”,形成,形成一条链,相邻两结点间用一个指针将两者连到一一条链,相邻两结点间用一个指针将两者连到一起。起。结构的概念与应用结构的概念与应用3依上图有依上图有7个结点个结点(x1,y1)(x1,y1)(x2,y2)(x2,y2)(x6,y6)(x6,y6)(x7,y7)(x7,y7)为了表示这种既有数据又有指针的情况,为了表示这种既有数据又有指针的情况,引入结构这种数据类型。引入结构这种数据类型。411.7 11.7
2、用指针处理链表用指针处理链表链表是程序设计中一种重要的动态数据结构,链表是程序设计中一种重要的动态数据结构,它是动态地进行存储分配的一种结构。它是动态地进行存储分配的一种结构。动态性体现为:动态性体现为:n链表中的元素个数可以根据需要增加和减少,不链表中的元素个数可以根据需要增加和减少,不像数组,在声明之后就固定不变;像数组,在声明之后就固定不变;n元素的位置可以变化,即可以从某个位置删除,元素的位置可以变化,即可以从某个位置删除,然后再插入到一个新的地方;然后再插入到一个新的地方;512491249 A A13561356 B B14751475 C C10211021 D DNullNul
3、l1 1、链表中的元素称为、链表中的元素称为“结点结点”,每个结点包括两,每个结点包括两个域:个域:数据域和指针域;数据域和指针域;2 2、单向链表通常由一个头指针(、单向链表通常由一个头指针(head)head),用于指向,用于指向链表头;链表头;3 3、单向链表有一个尾结点,该结点的指针部分指、单向链表有一个尾结点,该结点的指针部分指向一个空结点向一个空结点(NULL) (NULL) 。Head 1249 1356 1475 1021结点里的指针是存放下一个结点的地址6链表中结点的定义链表中结点的定义q链表是由结点构成的,链表是由结点构成的, 关键是定义结点关键是定义结点; ;q链表的结点
4、定义打破了先定义再使用的限制链表的结点定义打破了先定义再使用的限制, ,即可以用自己定义自己;即可以用自己定义自己;q递归函数的定义也违反了先定义再使用;递归函数的定义也违反了先定义再使用;这是这是C C语言程序设计上的两大特例语言程序设计上的两大特例7链表的基本操作链表的基本操作对链表的基本操作有:对链表的基本操作有:(1 1)创建链表是创建链表是指,从无到有地建立起一个链表,指,从无到有地建立起一个链表,即往空链表中依次插入若干结点,并保持结点即往空链表中依次插入若干结点,并保持结点之间的前驱和后继关系。之间的前驱和后继关系。(2 2)检索操作检索操作是指,按给定的结点索引号或检索是指,按
5、给定的结点索引号或检索条件,查找某个结点。如果找到指定的结点,条件,查找某个结点。如果找到指定的结点,则称为检索成功;否则,称为检索失败。则称为检索成功;否则,称为检索失败。(3 3)插入操作插入操作是指,在结点是指,在结点k ki-1i-1与与k ki i之间插入一个之间插入一个新的结点新的结点k k,使线性表的长度增,使线性表的长度增1 1,且,且k ki-1i-1与与k ki i的的逻辑关系发生如下变化:逻辑关系发生如下变化:插入前,插入前,k ki-1i-1是是k ki i的前驱,的前驱,k ki i是是k ki-1i-1的后继;插入后,的后继;插入后,新插入的结点新插入的结点k k成
6、为成为k ki-1i-1的后继、的后继、k ki i的前驱的前驱. .8(4 4)删除操作删除操作是指,删除结点是指,删除结点k ki i,使线性表的长度,使线性表的长度减减1 1,且,且k ki-1i-1、k ki i和和k ki+1i+1之间的逻辑关系发生如下变之间的逻辑关系发生如下变化:化:删除前,删除前,k ki i是是k ki+1i+1的前驱、的前驱、k ki-1i-1的后继;删除后,的后继;删除后,k ki-1i-1成为成为k ki+1i+1的前驱,的前驱,k ki+1i+1成为成为k ki-1i-1的后继的后继. .(5)(5)打印输出打印输出9一个指针类型的成员既可指向其它类型
7、的结构体一个指针类型的成员既可指向其它类型的结构体数据,也可以指向自己所在的结构体类型的数据数据,也可以指向自己所在的结构体类型的数据991019910189.589.59910399103909099107991078585numScorenextnext是是struct student类型中的一个成员,类型中的一个成员,它又它又指向指向struct student类型类型的数据。的数据。换名话说:换名话说:next存放下一个结点的地址存放下一个结点的地址1011.7.2 11.7.2 简单链表简单链表#define NULL 0struct student long num; float
8、score; struct student *next; ;main() struct student a, b, c, *head, *p; a.num=99101; a.score=89.5; b. num=99103; b.score=90; c.num=99107 ; c.score=85; head=&a; a.next=&b; b.next=&c; c.next=NULL; p=head; do printf(%ld %5.1fn,p-num,p-score); p=p-next; while(p!=NULL); 例例11.7建建立立和和输输出出一一个个简简
9、单单链链表表各结点在程序中定义,不是临时开辟的,各结点在程序中定义,不是临时开辟的,始终占有内容始终占有内容不放不放,这种链表称为,这种链表称为“静静态链表态链表”11 11.7.3 11.7.3 处理动态链表所需的函数处理动态链表所需的函数C C 语言使用系统函数语言使用系统函数动态动态开辟和释放存储单元开辟和释放存储单元1.malloc 1.malloc 函数函数 函数原形:函数原形:void void * *malloc(unsigned int size);malloc(unsigned int size);作用:作用:在内存的动态存储区中分配在内存的动态存储区中分配 一个一个 长度为
10、长度为sizesize的连续空间。的连续空间。返回值:返回值:是一个指向分配域起始地址的指针(基本是一个指向分配域起始地址的指针(基本类型类型voidvoid)。)。执行失败:执行失败:返回返回NULLNULL12函数原形函数原形: :void *calloc(unsigned n,unsigned size);作用:作用:在内存动态区中分配在内存动态区中分配 n n个个 长度为长度为sizesize的的连续空间。连续空间。函数返回值函数返回值:指向分配域起始地址的指针:指向分配域起始地址的指针执行失败:返回执行失败:返回nullnull主要用途主要用途:为一维数组开辟动态存储空间。:为一维数
11、组开辟动态存储空间。n n 为为数组元素个数,每个元素长度为数组元素个数,每个元素长度为sizesize2. calloc2. calloc 函数函数133. free 3. free 函数函数函数原形:函数原形: void free(void void free(void * *p p););作用:作用:释放由释放由 p p 指向的内存区。指向的内存区。P:P:是最近一次调用是最近一次调用 calloc calloc 或或 malloc malloc 函数函数时返回的值。时返回的值。free free 函数无返回值函数无返回值动态分配的存储单元在用完后一定要释放,动态分配的存储单元在用完后一
12、定要释放,否则内存会因申请空间过多引起资源不足否则内存会因申请空间过多引起资源不足而出现故障。而出现故障。14结点的动态分配结点的动态分配ANSI C ANSI C 的三个函数的三个函数( (头文件头文件 malloc.h) void malloc.h) void * *malloc(unsigned int size)malloc(unsigned int size)void void * *calloc(unsigned n, unsigned size)calloc(unsigned n, unsigned size)void free(void void free(void * *p)
13、p)C+ C+ 的两个函数的两个函数new new 类型(初值)类型(初值) delete delete 指针变量指针变量 / /* * 表示释放数组,可有可无)表示释放数组,可有可无)* */ /使用使用 new new 的优点:的优点:可以通过对象的大小直接分配,而不管对象可以通过对象的大小直接分配,而不管对象的具体长度是多少(的具体长度是多少(p340 p340 例例14.1014.10)1511.7.4 11.7.4 建立动态链表建立动态链表基本方法基本方法: : 三个结点(头结点三个结点(头结点headhead、尾结点、尾结点 NULL NULL 和待插入结点和待插入结点 P P)第
14、一步:定义头结点第一步:定义头结点headhead、尾结点、尾结点 p2p2 和待插入结点和待插入结点p1p1,待插入的结点数据部分初始化;待插入的结点数据部分初始化;第二步:该结点被头结点、尾结点同时指向第二步:该结点被头结点、尾结点同时指向。P1=p2=(struct studentP1=p2=(struct student* *)malloc(LEN);)malloc(LEN);头指针部分为头指针部分为空空,head=NULL;head=NULL; 第三步:重复申请待插入结点空间,对该结点的数据部第三步:重复申请待插入结点空间,对该结点的数据部分赋值(或输入值),将该结点插入在最前面,或
15、者最分赋值(或输入值),将该结点插入在最前面,或者最后面(书上在尾部插入)后面(书上在尾部插入). . P2-next=P1; P2=P1;P2-next=P1; P2=P1; 最后最后:P2-next=NULL;:P2-next=NULL;* *head,head,* *p1,p1,* *p2p2使用使用malloc(LEN)malloc(LEN)P2-next=NULL;1611.7.4 11.7.4 建立动态链表建立动态链表991019910189.589.5headP1p21. .任务是开辟结点和输入数据任务是开辟结点和输入数据2.2.并建立前后相链的关系并建立前后相链的关系待插入的结
16、点待插入的结点p1p1数数据部分初始化据部分初始化, ,该结该结点被头结点点被头结点head、尾结点尾结点p2同时指向同时指向.17图图11.1411.14991019910189.589.5headp299103991039090p1991019910189.589.5headp299103991039090p1(a)(b)p1重复申请待插入重复申请待插入结点空间,对该结结点空间,对该结点的数据部分赋值点的数据部分赋值(或输入值)(或输入值)P2-next P2-next 指向指向p1p1新开辟的结点。新开辟的结点。18图图11.1411.14head991019910189.589.5p1
17、p299103991039090(c)P2P2指向新结指向新结点点p2=p1p2=p119图图11.1511.15991019910189.589.5991019910189.589.5p299107991078585p1head991019910189.589.5991019910189.589.5p299107991078585p1head(a)(b)20 图图11.1611.169910399103909099107991078585p20 00 0p1head991019910189.589.59910399103909099107991078585NULLNULLp20 00 0p1
18、head991019910189.589.521例例11.8 11.8 建立一个有建立一个有3 3名学生数据的单向动态链表名学生数据的单向动态链表#define NULL 0#define LEN sizeof(struct student)struct studentlong num; float score; struct student *next; ;int n;struct student *creat(void) struct student *head; struct student*p1,*p2; n=0; p1=p2=(struct student*) malloc(LEN)
19、; scanf(%1d,%f,&p1-num,&p1-score); head=NULL;结构体类型数据的长度,结构体类型数据的长度,sizeofsizeof是是“字节数运算字节数运算符符”定义指针类型的函数。带回链表的起始地址定义指针类型的函数。带回链表的起始地址开辟长度为开辟长度为LENLEN的内存区的内存区P1,p2P1,p2是指向结构体类型数据的指针变是指向结构体类型数据的指针变量,强行转换成结构体类型量,强行转换成结构体类型假设头指向空结点假设头指向空结点22续续while(p1-num!=0) n=n+1; /*n 是结点的个数是结点的个数*/ if(n=1)hea
20、d=p1; else p2-next=p1; p2=p1; p1=(struct student*)malloc(LEN); scanf(%1d,%f,&p1-num,&p1-score); p2-next=NULL; return(head); /返回链表的头返回链表的头指针指针算法:算法:p1指向新开的结点指向新开的结点: p1=(stuct student*)malloc(LEN);p1的所指向的结点连接在的所指向的结点连接在p2所指向结点后面,用所指向结点后面,用p2-next=p1来实现。来实现。p2 指向链表中最后建立的结点,指向链表中最后建立的结点,: p2=p1
21、; 头指针指向头指针指向p1结点结点P1开辟的新结点链到了开辟的新结点链到了p2的后面的后面P1继续开辟新结点继续开辟新结点给新结点赋值此给新结点赋值此2311.7.5 11.7.5 输出链表输出链表链表遍历链表遍历1.1.单向链表总是从头结点开始的;单向链表总是从头结点开始的;2.2.每访问一个结点,就将当前指针向该每访问一个结点,就将当前指针向该结点的下一个结点移动:结点的下一个结点移动: p=p-nextp=p-next; ;3.3.直至下一结点为空直至下一结点为空 P=NULLP=NULL24图图 11.1811.18headp PPNULLNULL25例题例题 9 9void pri
22、nt (struct student *head) struct student * p; printf(nNow,These %d records are:n,n); p=head; if(head!=NULL) do printf(%ld %5.lfn,p - num,p - score); p=p - next; while(p!=NULL); 2611.7.6 11.7.6 对链表的删除操作对链表的删除操作删除结点原则:删除结点原则:不改变原来的排列顺序,只是从链表中分离开来,不改变原来的排列顺序,只是从链表中分离开来,撤消原来的链接关系。撤消原来的链接关系。两种情况:两种情况:1 1
23、、要删的结点是头指针所指的结点则直接操作;、要删的结点是头指针所指的结点则直接操作;2 2、不是头结点,要依次往下找。、不是头结点,要依次往下找。另外要考虑:空表和找不到要删除的结点另外要考虑:空表和找不到要删除的结点27链表中结点删除链表中结点删除需要由两个临时指针:需要由两个临时指针:P1: P1: 判断指向的结点是不是要删除的结点判断指向的结点是不是要删除的结点(用于寻找);(用于寻找);P2: P2: 始终指向始终指向P1P1的前面一个结点;的前面一个结点;28图图11.1911.19ABDECABDEC(a) (B)29图图11.2011.209910199101headp19910
24、3991039910799107NULLNULL(a)(b)9910199101head99103991039910799107NULLNULLp2p1原链表原链表P1指向指向头结点头结点P2指向指向p1指向的结指向的结点。点。P1指指向下移一向下移一个结点。个结点。30图图11.2011.209910199101head99103991039910799107NULLNULLp19910199101head99103991039910799107NULLNULLp2p1(c)(d)经判断后,第经判断后,第1个结点是要删除个结点是要删除的结点,的结点,head指指向第向第2个结点,个结点,第第
25、1个结点脱离。个结点脱离。经经P1P1找到要删找到要删除的结点后使除的结点后使之脱离。之脱离。31例例 题题 1010struct student *del( struct student *head, long num ) struct student *p1, *p2; if(head=NULL) printf(nlist null!n); goto end; p1=head; while(num!=p1-num&p1-next!=NULL) p2=p1; p1=p1-next; if(num=p1-num) if(p1=head) head=p1-next; else p2-ne
26、xt=p1-next; printf(delete:%ldn,num); n=n-1; else printf(%ld not been found!n,num); end: return(head); 找到了找到了没找到没找到3211.7.7 11.7.7 对链表的插入操作对链表的插入操作插入结点:将一个结点插入到已有的链表中插入结点:将一个结点插入到已有的链表中插入原则:插入原则:1 1、插入操作不应破坏原链接关系、插入操作不应破坏原链接关系2 2、插入的结点应该在它该在的位置、插入的结点应该在它该在的位置实现方法:实现方法: 应该有一个插入位置的查找子过程应该有一个插入位置的查找子过程共
27、有三种情况:共有三种情况:1 1、插入的结最小、插入的结最小2 2、插入的结点最大、插入的结点最大3 3、插入的结在中间、插入的结在中间33 操操 作作 分分 析析同删除一样,需要几个临时指针:同删除一样,需要几个临时指针:P0: P0: 指向待插的结点指向待插的结点; ;初始化:初始化:p0=p0=数组数组stu;stu;P1: P1: 指向要在指向要在P1P1之前插入结点;初始化之前插入结点;初始化: p1=head;: p1=head;P2: P2: 指向要在指向要在P2P2之后插入结点;之后插入结点;插入操作:当符合以下条件时:插入操作:当符合以下条件时:p0-num p0-num 与
28、与 p1-num p1-num 比较找位置比较找位置if(p0if(p0-nump1-num)&(p1-next!=NULL) 则插入的结点不在则插入的结点不在p1所指结点之前;指针后移,交给所指结点之前;指针后移,交给p2; p1= p1-next; p2=p1;p1-next; p2=p1;则继续与则继续与 p0 指向的数组去比,直到指向的数组去比,直到(p1-next!=NULL)为止。为止。 否则有两种情况发生:否则有两种情况发生: if(head=p1) head=p0;p0-next=p1if(head=p1) head=p0;p0-next=p1插到原来第一个结插到原来第
29、一个结点点之前之前;else p2-next=p0;p0-next=p1;-next=p0;p0-next=p1; 插到插到 p2 指向的结点指向的结点之后之后;还有另外一种情况:插到还有另外一种情况:插到最后最后的结点之后;的结点之后;p1-next=p0;p0-next=NULL;-next=p0;p0-next=NULL;34图图11.2211.229910199101headp199103991039910799107NULLNULL(a)9910299102p035图图11.2211.229910199101head99103991039910799107NULLNULL991029
30、9102p0p2p1(b)36例例 题题 1111struct student insert(struct student *head,struct student *stud) struct student *p0,*p1,*p2; p1=head; p0=stud; if( head=NULL; ) head=p0;p0-next=NULL; else while( p0-nump1-num)&(p1-next! =NULL) p2=p1; p1=p1-next; if( p0-numnum) if(head=p1) head=p0; else p2-next=p0; p0-nex
31、t=p1; else p1-next=p0;p0-next=NULL; n=n+1; return(head); 原来的链表是空表原来的链表是空表P0P0指向要插的结点指向要插的结点使使p0p0指向的结点作为头结点指向的结点作为头结点使使p2指向刚才指向刚才p1指向的结点指向的结点插到原来第一个结点之前插到原来第一个结点之前插到插到p2指向的结点之后指向的结点之后插到最后的结点之后插到最后的结点之后链接375 5head6 610101515null12128 8课堂举例:课堂举例:已有一个如图所示的链表;已有一个如图所示的链表;它是按结点中的整数域从小到大排序的,现在要它是按结点中的整数域从
32、小到大排序的,现在要插入一个结点,该结点中的数为插入一个结点,该结点中的数为1010待插入结点待插入结点此结点已插入链表此结点已插入链表38分析:分析:按三种情况按三种情况1 1、第一种情况,链表还未建成(空链表),待插入结、第一种情况,链表还未建成(空链表),待插入结点点p p实际上是第一个结点。这时必然有实际上是第一个结点。这时必然有head=nullhead=null。只要让头指针指向只要让头指针指向 p p 就可以了。语句为就可以了。语句为6nullheadphead = p;p-next = null;2 2、第二种情况,链表已建成,待插入结点、第二种情况,链表已建成,待插入结点 p
33、 p 的数据的数据要比头结点的数据还要小,这时有要比头结点的数据还要小,这时有( (p-num )num)p-num )num)当然当然p p结点要插在结点要插在headhead结点前。结点前。396head8512nullheadpp-next=head;head=p;语句为语句为null403 3、第三种情况,链表已建成,待插入结点、第三种情况,链表已建成,待插入结点 p p 的数据比头结点的数据大,需要找到正确的数据比头结点的数据大,需要找到正确的插入位置。这时,可以借助两个结构指的插入位置。这时,可以借助两个结构指针针r r 和和 g g,利用循环比较来找到正确位置。,利用循环比较来找
34、到正确位置。然后将结点然后将结点 p p 插入到链表中正确的位置。插入到链表中正确的位置。参见下面的图示参见下面的图示416head81213nullp15gr说明:说明:这种情况下,这种情况下,p p 结点已经与链表的第一个结点结点已经与链表的第一个结点比较过了,所以从链表的下一个结点开始比较。比较过了,所以从链表的下一个结点开始比较。138138,继续比较。,继续比较。426head81213nullp15gr说明:说明:13121312,继续比较。,继续比较。436head81213p15grnull说明:说明:131513next = p;p-next = g;44/ 结构结构7.c#
35、include #include / / 预编译命令预编译命令#include #include / / 内存空间分配内存空间分配#define null 0#define null 0/ / 定义空指针常量定义空指针常量#define LEN sizeof(struct numST)#define LEN sizeof(struct numST)/ / 定义常量,表示定义常量,表示结构长度结构长度struct numSTstruct numST/ / 结构声明结构声明 int num;int num;/ / 整型数整型数struct numST struct numST * *next;ne
36、xt;/ numST/ numST结构指针结构指针; ;参考程序参考程序45/ 被调用函数被调用函数insert(),两个形参分别表示链表和待插入的结点,两个形参分别表示链表和待插入的结点void insert (struct numST *phead, struct numST *p)/ 函数体开始函数体开始struct numST *q,*r;/ 定义结构指针定义结构指针q,rif (*phead)=null)/ 第一种情况第一种情况,链表为空,链表为空*phead = p;/ 链表头指向链表头指向preturn;/ 完成插入操作,返回完成插入操作,返回else/ 链表不为空链表不为空/
37、第二种情况第二种情况,p结点结点num值小于链表头结点的值小于链表头结点的num值值if ( (*phead)-num p-num) / 将将p结点插到链表头部结点插到链表头部 p-next = *phead;/ 将将p的的next指针指向链表头指针指向链表头(*phead) *phead = p;/ 将链表头赋值为将链表头赋值为p return;/ 返回返回46/ 第三种情况第三种情况,循环查找正确位置,循环查找正确位置r = *phead;/ r赋值为链表头赋值为链表头q = (*phead)-next; / q赋值为链表的下一个结点赋值为链表的下一个结点while (q!=null) /
38、 利用循环查找正确位置利用循环查找正确位置/ 判断当前结点判断当前结点num是否小于是否小于p结点的结点的numif (q-num num)r = q; / r赋值为赋值为q,即指向,即指向q所指的结点所指的结点q = q-next;/ q指向链表中相邻的下一个结点指向链表中相邻的下一个结点else/ 找到了正确的位置找到了正确的位置break;/ 退出循环退出循环/ 将将p结点插入正确的位置结点插入正确的位置r-next = p;p-next = q;47/ 被调用函数,形参为被调用函数,形参为ST结构指针结构指针,用于输出链表内容,用于输出链表内容void print(struct num
39、ST *head) int k=0;/ 整型变量,用于计数整型变量,用于计数struct numST * r;/ 声明声明r为为ST结构指针结构指针r=head;/ r赋值为赋值为head,即指向,即指向链表头链表头while(r != null)/ 当型循环,链表指针不为空当型循环,链表指针不为空则继续则继续/ 循环体开始循环体开始k=k+1;/ 计数加计数加1printf(%d %dn,k,r-num); r=r-next;/ 取链表中相邻的下一个结点取链表中相邻的下一个结点/ 循环体结束循环体结束48void main()/ 主函数开始主函数开始/ 函数体开始函数体开始struct nu
40、mST *head, *p;/ ST型结构指针型结构指针head = null;/ 分配两个分配两个ST结构的内存空间,用于构造链表结构的内存空间,用于构造链表head = (struct numST *) malloc(LEN);head-next = (struct numST *) malloc(LEN);/ 为链表中的两个结点中的为链表中的两个结点中的num赋值为赋值为5和和10head-num = 5;head-next-num = 10;head-next-next = null; / 链表尾赋值为空链表尾赋值为空/ 构造一个结点构造一个结点p,用于插入链表,用于插入链表p = (
41、struct numST *) malloc(LEN);p-num = 8;p-next = null;insert(&head, p);/ 调用调用create函数建立链表,函数建立链表,print(head);/ 调用调用print函数,输出链表内容函数,输出链表内容/ 主函数结束主函数结束49说明:说明:函数函数insert()的第一个形参为的第一个形参为struct numST*类型,即类型,即“指针的指针指针的指针”。调用时送入的实参是。调用时送入的实参是链表头指针的地址,即程序中的链表头指针的地址,即程序中的&head。这样对。这样对head的修改才会在函数返回后仍
42、有效。如果形参的修改才会在函数返回后仍有效。如果形参为为struct numST*,则传入的为指针,当函数返回,则传入的为指针,当函数返回后,后,head无法改变。无法改变。5011.8 11.8 共用体共用体 构造类型之二构造类型之二联合联合在同一存储单元里,根据需要放不同类型的数据,在同一存储单元里,根据需要放不同类型的数据,使用覆盖技术。使用覆盖技术。5111.8.1 11.8.1 概念概念单元起始地址:单元起始地址:1000 1000 。三个变量(数据)占用同。三个变量(数据)占用同一单元:一单元:1000 1000 1003 1003浮点型(浮点型(4 byte)字符型(字符型(1
43、byte)整型(整型(2Byte)52共用体变量的定义共用体变量的定义格式(一般形式):格式(一般形式): union union 联合类型名联合类型名 成员列表成员列表 变量列表;变量列表;11.8.2 11.8.2 共用体变量的引用方式共用体变量的引用方式同结构类型变量的引用格式:同结构类型变量的引用格式: 变量名变量名. .成员名成员名53格式与结构类型的定义和变量声明形格式与结构类型的定义和变量声明形式上类似,但实质上有区别:式上类似,但实质上有区别:1.1.结构类型的长度结构类型的长度= =各成员的长度和;各各成员的长度和;各成员占独立的存储单元,不共享;成员占独立的存储单元,不共享
44、;2.2.联合类型的长度为成员中长度的最大者,联合类型的长度为成员中长度的最大者,各成员共享长度最大的存储单元;各成员共享长度最大的存储单元;5411.8.3 11.8.3 共用体类型数据的特点共用体类型数据的特点虽然同一内存单元内可以存放不同类型虽然同一内存单元内可以存放不同类型(同一地址)、不同长度的数据,但任(同一地址)、不同长度的数据,但任一时刻,只有一种类型数据(最后赋值一时刻,只有一种类型数据(最后赋值的)起作用;其它的都没有意义;的)起作用;其它的都没有意义;不能对共用体变量整体赋值,也不能对不能对共用体变量整体赋值,也不能对其初始化。其初始化。共用变量不可作为函数的参数,但可以
45、共用变量不可作为函数的参数,但可以通过指针指向;通过指针指向;共用体类型可以和结构类型共用体类型可以和结构类型/ /数组类型互数组类型互为基类型;为基类型;p289p28955例例 题题 1212structstruct int num; int num; char name10; char name10; char sex; char job; char sex; char job; union union int class; char position10; int class; char position10; category; category; person2; person2;
46、main()main() int n,i; int n,i; for(i=0;i2 ;i+); for(i=0;i2 ;i+); s c a n f ( % d s c a n f ( % d , % s% s , % c% c , % c% c ” , , &personi.num,,&personi.sex,&personi.num,,&personi.sex,&personi.job);&personi.job);56 if(personi.job=s) if(personi.job=s) s
47、canf(%d,&personi.category.class); scanf(%d,&personi.category.class); else if(personi.job=t) else if(personi.job=t) scanf(%s,personi.category.position); scanf(%s,personi.category.position); else printf(input error!); else printf(input error!); printf(n); printf(n); printf(no. name sex job cla
48、ss/positionn); printf(no. name sex job class/positionn);for(i=0;i2;i+)for(i=0;iSunMonSun、SatSat最大。最大。(4 4)枚举元素的值也是可以人为改变的:在定义时由程)枚举元素的值也是可以人为改变的:在定义时由程序指定。序指定。例如,如果例如,如果enum weekdays Sun=enum weekdays Sun=, Mon, Mon ,Tue, ,Tue, Wed, Thu, Fri, SatWed, Thu, Fri, Sat;则;则Sun=Sun=,Mon=Mon=,从,从Tue=2Tue=2开
49、开始,依次增。始,依次增。61例例 题题 1313/ /* *file1.cfile1.c文件文件1 1* */ /main()main() extern enter-string(char str80); extern enter-string(char str80); extern delete-string(char str,char ch); extern delete-string(char str,char ch); extern print-string(char str); extern print-string(char str); char c; char str80; c
50、har c; char str80; enter_string(str); scanf(%c,&c); enter_string(str); scanf(%c,&c); delete_string(str,c); print_string(str); delete_string(str,c); print_string(str);/ /* * file2.c file2.c 文件文件2 2* */ /#include#includeenter_string(char str80)enter_string(char str80)gets(str);gets(str);62续续fo
51、r(i=0;i2;i+)for(i=0;i2;i+) if(personi.job=s) if(personi.job=s) p r i n t f ( % - 6 d % - 1 0 s % - 3 c % - 3 c % - p r i n t f ( % - 6 d % - 1 0 s % - 3 c % - 3 c % -6dn,personi.num,,personi.6dn,personi.num,,personi. sex,personi.job,personi.category.class);sex,personi.job,per
52、soni.category.class); else else p r i n t f ( % - 6 d % - 1 0 s % - 3 c % - 3 c % - p r i n t f ( % - 6 d % - 1 0 s % - 3 c % - 3 c % -6sn,personi.num,,personi.6sn,personi.num,,personi. sex,personi.job,personi.category.positiosex,personi.job,personi.category.position); n); 63
53、11.10 11.10 用用typedef typedef 为类型定义新名字为类型定义新名字 除可直接使用提供的标准类型和自定义除可直接使用提供的标准类型和自定义的类型的类型(结构、共用、枚举)外,也可使用(结构、共用、枚举)外,也可使用typedeftypedef定义已有类型的别名。该别名与标定义已有类型的别名。该别名与标准类型名一样,可用来定义相应的变量。准类型名一样,可用来定义相应的变量。定义已有类型别名的方法如下:定义已有类型别名的方法如下: (1 1)按定义变量的方法,写出定义体;)按定义变量的方法,写出定义体; (2 2)将变量名换成别名;)将变量名换成别名; (3 3)在定义体最
54、前面加上)在定义体最前面加上typedeftypedef。 6411.10 11.10 用用typeded typeded 为类型定义新名字为类型定义新名字任何已有的类型可以重新命名任何已有的类型可以重新命名typedef long integer;typedef long integer; /将将 long long 重新命名为重新命名为 integerinteger,使得,使得 integer integer 和和 long long 同等使用同等使用 可以和新类型定义一起定义名字可以和新类型定义一起定义名字typedef int ARR10 ; typedef int ARR10 ; /
55、 / 定义了一个数组名定义了一个数组名 ARRARR,它是具有,它是具有1010个元素的整型个元素的整型数组类型数组类型typedef struct int num;typedef struct int num;float score;float score; S; S; / /* *定义结构体别名为定义结构体别名为S S* */ /STUDENT stu1;STUDENT stu1;65讨论:讨论:typedef typedef 和和 #define#define说明说明:(1 1)用)用typedeftypedef只是给已有类型增加个别名,只是给已有类型增加个别名,并不能创造个新的类型。就
56、如同人一样,除并不能创造个新的类型。就如同人一样,除学名外,可以再取一个小名(或雅号),但并学名外,可以再取一个小名(或雅号),但并不能创造出另一个人来。不能创造出另一个人来。(2 2)typedeftypedef与与#define#define有相似之处,但二者是有相似之处,但二者是不同的:前者是由编译器在编译时处理的;后不同的:前者是由编译器在编译时处理的;后者是由编译预处理器在编译预处理时处理的,者是由编译预处理器在编译预处理时处理的,而且只能作简单的字符串替换。而且只能作简单的字符串替换。66struct TMint x,y; / 结构结构TM的成员,的成员,x,y为整数型为整数型st
57、ruct TM next / 结构结构TM的成员,属的成员,属TM型型下面的表是马的跳步方案,从左下角跳到右上角下面的表是马的跳步方案,从左下角跳到右上角结点n1n2n3n4n5n6n7xy00122443647284结构体与共体例子678 84 4NULLNULLNULL为空地址为空地址下面是形成链表的一个参考程序下面是形成链表的一个参考程序2 24 4&n41 12 2&n30 00 0&n2&n1head68/ 结构结构1.c#include / 预编译命令预编译命令#define null 0/ 定义空指针常量定义空指针常量struct TM/ 定义结构
58、定义结构TMint x,y;/ 整型变量整型变量x,ystruct TM next;/ 指向指向TM结构的指针结构的指针;void main()/ 主函数主函数/ 主函数开始主函数开始 int i;/ 声明整型变量声明整型变量 / 声明声明TM结构结构n1n7,结构指针结构指针head,p struct TM n1,n2,n3,n4,n5,n6,n7, head, p; 69 / 分别对分别对TM结构结构n1n7中的中的x,y赋赋值值 n1.x=0;n1.y=0; n2.x=1;n2.y=2; n3.x=2;n3.y=4; n4.x=4;n4.y=4; n5.x=6;n5.y=4; n6.x=
59、7;n6.y=2; n7.x=8;n7.y=4; / head赋值为赋值为n1,即,即head指向指向n1 head=&n1; / n1n7构成链表构成链表 n1.next=&n2; n2.next=&n3; n3.next=&n4; n4.next=&n5; n5.next=&n6; n6.next=&n7; / n7的的next指针赋值为空指针指针赋值为空指针 n7.next=null;70p=head;p=head; / p/ p赋值为赋值为headhead,即,即p p指向指向headhead所指所指的内容的内容i=1;i=1;/
60、 i/ i赋值为赋值为1 1dodo/ / 直到型循环直到型循环 / / 循环体开始循环体开始/ / 输出结点信息输出结点信息printf(printf(结点结点%d: x=%d, y=%dn,i,p-x,p-y);%d: x=%d, y=%dn,i,p-x,p-y); p=p-next;p=p-next;/ p/ p指向下一个结点指向下一个结点 i=i+1;i=i+1;/ / 计数加计数加1 1 while(p!=null); while(p!=null);/ / 未到达链表尾部,则继续循未到达链表尾部,则继续循环环 / / 主函数结束主函数结束71用结构数组,利用键盘输入结点中的数据。重用结构数组,利用键盘输入结点中的数据。重点看点看scanf(scanf(“%d%d”,&a);,&a);ni.x=a;ni.x=a;结构数组,数组中的元素为结构类型的数据,结构数组,数组中的元素为结构类型的数据,如如n8n8/ 结构结构2.c#include / 预编译命令预编译命令#defin
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年林业服务项目提案报告模板
- 分娩期护理要领课件
- 民工摩擦调解协议书
- 景区用火安全协议书
- 液压闸刀转让协议书
- 教育机构外派协议书
- 林地木头转让协议书
- 旧房翻建东西协议书
- 楼板终身质保协议书
- 校园安保服务协议书
- 山东省2025届高三第二次模拟考试历史试卷含解析
- DL∕Z 860.1-2018 电力自动化通信网络和系统 第1部分:概论
- 2024年04月南昌市2024年第二次招考120名市级专职留置看护队员笔试笔试历年典型考题及考点研判与答案解析
- 康养旅游项目策划方案毕业设计(2篇)
- 《陆上风电场工程概算定额》NBT 31010-2019
- 《论语》全文原文版
- 流体机械复习题1
- 家装设计师量房技巧
- 《水电工程水生生态调查与评价技术规范》(NB-T 10079-2018)
- 2024年注册消防工程师题库(全国通用)
- 静脉留置针使用及维护培训课件
评论
0/150
提交评论