




已阅读5页,还剩7页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
-一、单链表的建立 有了动态内存分配的基础,要实现链表就不难了。所谓链表,就是用一组任意的存储单元存储线性表元素的一种数据结构。链表又分为单链表、双向链表和循环链表等。我们先讲讲单链表。所谓单链表,是指数据接点是单向排列的。一个单链表结点,其结构类型分为两部分:1、数据域:用来存储本身数据2、链域或称为指针域:用来存储下一个结点地址或者说指向其直接后继的指针。例:typedef struct nodechar name20;struct node *link;stud;这样就定义了一个单链表的结构,其中char name20是一个用来存储姓名的字符型数组,指针*link是一个用来存储其直接后继的指针。定义好了链表的结构之后,只要在程序运行的时候爱数据域中存储适当的数据,如有后继结点,则把链域指向其直接后继,若没有,则置为NULL。下面就来看一个建立带表头(若未说明,以下所指链表均带表头)的单链表的完整程序。#include #include /*包含动态内存分配函数的头文件*/#define N 10 /*N为人数*/ typedef struct nodechar name20;struct node *link; stud; stud * creat(int n) /*建立单链表的函数,形参n为人数*/stud *p,*h,*s; /* *h保存表头结点的指针,*p指向当前结点的前一个结点,*s指向当前结点*/int i; /*计数器*/if(h=(stud *)malloc(sizeof(stud)=NULL) /*分配空间并检测*/printf(不能分配内存空间!);exit(0);h-name0=0; /*把表头结点的数据域置空*/h-link=NULL; /*把表头结点的链域置空*/p=h; /*p指向表头结点*/for(i=0;ilink=s; /*把s的地址赋给p所指向的结点的链域,这样就把p和s所指向的结点连接起来了*/printf(请输入第%d个人的姓名,i 1);scanf(%s,s-name); /*在当前结点s的数据域中存储姓名*/s-link=NULL;p=s;return(h);main()int number; /*保存人数的变量*/stud *head; /*head是保存单链表的表头结点地址的指针*/number=N;head=creat(number); /*把所新建的单链表表头地址赋给head*/这样就写好了一个可以建立包含N个人姓名的单链表了。写动态内存分配的程序应注意,请尽量对分配是否成功进行检测。二、单链表的基本运算 建立了一个单链表之后,如果要进行一些如插入、删除等操作该怎么办?所以还须掌握一些单链表的基本算法,来实现这些操作。单链表的基本运算包括:查找、插入和删除。下面我们就一一介绍这三种基本运算的算法,并结合我们建立单链表的例子写出相应的程序。1、查找对单链表进行查找的思路为:对单链表的结点依次扫描,检测其数据域是否是我们所要查好的值,若是返回该结点的指针,否则返回NULL。因为在单链表的链域中包含了后继结点的存储地址,所以当我们实现的时候,只要知道该单链表的头指针,即可依次对每个结点的数据域进行检测。 以下是应用查找算法的一个例子:#include #include #include /*包含一些字符串处理函数的头文件*/#define N 10typedef struct nodechar name20;struct node *link;stud;stud * creat(int n) /*建立链表的函数*/stud *p,*h,*s;int i;if(h=(stud *)malloc(sizeof(stud)=NULL)printf(不能分配内存空间!);exit(0);h-name0=0;h-link=NULL;p=h;for(i=0;ilink=s;printf(请输入第%d个人的姓名,i 1);scanf(%s,s-name);s-link=NULL;p=s;return(h);stud * search(stud *h,char *x) /*查找链表的函数,其中h指针是链表的表头指针,x指针是要查找的人的姓名*/stud *p; /*当前指针,指向要与所查找的姓名比较的结点*/char *y; /*保存结点数据域内姓名的指针*/p=h-link;while(p!=NULL)y=p-name;if(strcmp(y,x)=0) /*把数据域里的姓名与所要查找的姓名比较,若相同则返回0,即条件成立*/return(p); /*返回与所要查找结点的地址*/else p=p-link;if(p=NULL)printf(没有查找到该数据!);main()int number;char fullname20;stud *head,*searchpoint; /*head是表头指针,searchpoint是保存符合条件的结点地址的指针*/number=N;head=creat(number);printf(请输入你要查找的人的姓名:);scanf(%s,fullname);searchpoint=search(head,fullname); /*调用查找函数,并把结果赋给searchpoint指针*/2、插入(后插)假设在一个单链表中存在2个连续结点p、q(其中p为q的直接前驱),若我们需要在p、q之间插入一个新结点s,那么我们必须先为s分配空间并赋值,然后使p的链域存储s的地址,s的链域存储q的地址即可。(p-link=s;s-link=q),这样就完成了插入操作。下例是应用插入算法的一个例子:#include #include #include #define N 10 typedef struct nodechar name20;struct node *link;stud;stud * creat(int n) /*建立单链表的函数*/stud *p,*h,*s;int i;if(h=(stud *)malloc(sizeof(stud)=NULL)printf(不能分配内存空间!);exit(0);h-name0=0;h-link=NULL;p=h;for(i=0;ilink=s;printf(请输入第%d个人的姓名:,i 1);scanf(%s,s-name);s-link=NULL;p=s;return(h);stud * search(stud *h,char *x) /*查找函数*/stud *p;char *y;p=h-link;while(p!=NULL)y=p-name;if(strcmp(y,x)=0)return(p);else p=p-link;if(p=NULL)printf(没有查找到该数据!);void insert(stud *p) /*插入函数,在指针p后插入*/char stuname20;stud *s; /*指针s是保存新结点地址的*/if(s= (stud *) malloc(sizeof(stud)=NULL)printf(不能分配内存空间!);exit(0);printf(请输入你要插入的人的姓名:);scanf(%s,stuname);strcpy(s-name,stuname); /*把指针stuname所指向的数组元素拷贝给新结点的数据域*/s-link=p-link; /*把新结点的链域指向原来p结点的后继结点*/p-link=s; /*p结点的链域指向新结点*/main()int number;char fullname20; /*保存输入的要查找的人的姓名*/stud *head,*searchpoint;number=N;head=creat(number); /*建立新链表并返回表头指针*/printf(请输入你要查找的人的姓名:);scanf(%s,fullname);searchpoint=search(head,fullname); /*查找并返回查找到的结点指针*/insert(searchpoint); /*调用插入函数*/3、删除假如我们已经知道了要删除的结点p的位置,那么要删除p结点时只要令p结点的前驱结点的链域由存储p结点的地址该为存储p的后继结点的地址,并回收p结点即可。以下便是应用删除算法的实例:#include #include #include #define N 10 typedef struct nodechar name20;struct node *link;stud;stud * creat(int n) /*建立新的链表的函数*/stud *p,*h,*s;int i;if(h=(stud *)malloc(sizeof(stud)=NULL)printf(不能分配内存空间!);exit(0);h-name0=0;h-link=NULL;p=h;for(i=0;ilink=s;printf(请输入第%d个人的姓名,i 1);scanf(%s,s-name);s-link=NULL;p=s;return(h);stud * search(stud *h,char *x) /*查找函数*/stud *p;char *y;p=h-link;while(p!=NULL)y=p-name;if(strcmp(y,x)=0)return(p);else p=p-link;if(p=NULL)printf(没有查找到该数据!);stud * search2(stud *h,char *x) /*另一个查找函数,返回的是上一个查找函数的直接前驱结点的指针,*/*h为表头指针,x为指向要查找的姓名的指针*/*其实此函数的算法与上面的查找算法是一样的,只是多了一个指针s,并且s总是指向指针p所指向的结点的直接前驱,*/*结果返回s即是要查找的结点的前一个结点*/stud *p,*s;char *y;p=h-link;s=h;while(p!=NULL)y=p-name;if(strcmp(y,x)=0)return(s);elsep=p-link;s=s-link;if(p=NULL)printf(没有查找到该数据!);void del(stud *x,stud *y) /*删除函数,其中y为要删除的结点的指针,x为要删除的结点的前一个结点的指针*/stud *s;s=y;x-link=y-link;free(s);main()int number;char fullname20;stud *head,*searchpoint,*forepoint;number=N;head=creat(number);printf(请输入你要删除的人的姓名:);scanf(%s,fullname);searchpoint=search(head,fullname);forepoint=search2(head,fullname);del(forepoint,searchpoint);一、循环链表 循环链表是与单链表一样,是一种链式的存储结构,所不同的是,循环链表的最后一个结点的指针是指向该循环链表的第一个结点或者表头结点,从而构成一个环形的链。循环链表的运算与单链表的运算基本一致。所不同的有以下几点:1、在建立一个循环链表时,必须使其最后一个结点的指针指向表头结点,而不是象单链表那样置为NULL。此种情况还使用于在最后一个结点后插入一个新的结点。 2、在判断是否到表尾时,是判断该结点链域的值是否是表头结点,当链域值等于表头指针时,说明已到表尾。而非象单链表那样判断链域值是否为NULL。二、双向链表双向链表其实是单链表的改进。当我们对单链表进行操作时,有时你要对某个结点的直接前驱进行操作时,又必须从表头开始查找。这是由单链表结点的结构所限制的。因为单链表每个结点只有一个存储直接后继结点地址的链域,那么能不能定义一个既有存储直接后继结点地址的链域,又有存储直接前驱结点地址的链域的这样一个双链域结点结构呢?这就是双向链表。在双向链表中,结点除含有数据域外,还有两个链域,一个存储直接后继结点地址,一般称之为右链域;一个存储直接前驱结点地址,一般称之为左链域。在c语言中双向链表结点类型可以定义为: typedef struct nodeint data; /*数据域*/struct node *llink,*rlink; /*链域,*llink是左链域指针,*rlink是右链域指针*/JD;当然,也可以把一个双向链表构建成一个双向循环链表。双向链表与单向链表一样,也有三种基本运算:查找、插入和删除假如我们已经知道了要删除的结点p的位置,那么要删除p结点时只要令p结点的前驱结点的链域由存储p结点的地址该为存储p的后继结点的地址,并回收p结点即可。 以下便是应用删除算法的实例:#include stdio.h#include malloc.h#include string.h#define N 10 typedef struct nodechar name20;struct node *link;stud;stud * creat(int n) /*建立新的链表的函数*/stud *p,*h,*s;int i;if(h=(stud *)malloc(sizeof(stud)=NULL)printf(不能分配内存空间!);exit(0);h-name0=0;h-link=NULL;p=h;for(i=0;in;i+)if(s= (stud *) malloc(sizeof(stud)=NULL)printf(不能分配内存空间!);exit(0);p-link=s;printf(请输入第%d个人的姓名,i+1);scanf(%s,s-name);s-link=NULL;p=s;return(h);stud * search(stud *h,char *x) /*查找函数*/stud *p;char *y;p=h-link;while(p!=NULL)y=p-name;if(strcmp(y,x)=0)return(p);else p=p-link;if(p
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 新兴市场与行业集中变化-洞察及研究
- 农村互联网金融风险防控-洞察及研究
- 文化地理学在灾害管理中的应用-洞察及研究
- 无纺布在纺织业的创新应用-洞察及研究
- 智能物流平台的数据安全策略-洞察及研究
- 动态图神经网络压缩策略-洞察及研究
- 文化敏感性在职场交流中的作用-洞察及研究
- 土壤水势与植被恢复-洞察及研究
- 全球视野下的文化认同构建-洞察及研究
- 云计算助力设计创意生成-洞察及研究
- 化肥欠款协议模板
- “对校园欺凌说不”主题班会课件
- PLC电气控制设计污水处理系统样本
- 青春筑梦强国有我
- 班组质量管理和现场管理培训
- 新一代5G网络-全网部署与优化
- 导学案:化学合成材料
- 高中通用技术作品设计方案七篇
- MT-T 1199-2023 煤矿用防爆柴油机无轨胶轮运输车辆通用安全技术条件
- Linux系统基础操作培训文档
- 石油化工工艺装置蒸汽管道配管的设计
评论
0/150
提交评论