实验二链表操作实现.docx
《实验二链表操作实现.docx》由会员分享,可在线阅读,更多相关《实验二链表操作实现.docx(15页珍藏版)》请在冰豆网上搜索。
实验二链表操作实现
实验二-链表操作实现
实验二链表操作实现
实验日期:
2017年3月16日
实验目的及要求
1.熟练掌握线性表的基本操作在链式存储上的实现;
2.以线性表的各种操作(建立、插入、删除、遍历等)的实现为重点;
3.掌握线性表的链式存储结构的定义和基本操作的实现;
4.通过本实验加深对C语言的使用(特别是函数的参数调用、指针类型的应用)。
实验内容
已知程序文件linklist.cpp已给出学生身高信息链表的类型定义和基本运算函数定义。
(1)链表类型定义
typedefstruct{
intxh;/*学号*/
floatsg;/*身高*/
intsex;/*性别,0为男生,1为女生*/
}datatype;
typedefstructnode{
datatypedata;/*数据域*/
structnode*next;/*指针域*/
}LinkNode,*LinkList;
(2)带头结点的单链表的基本运算函数原型
LinkListinitList();/*置一个空表(带头结点)*/
voidcreateList_1(LinkListhead);/*创建单链表*/
voidcreateList_2(LinkListhead);/*创建单链表*/
voidsort_xh(LinkListhead);/*单链表排序*/
voidreverse(LinkListhead);/*对单链表进行结点倒置*/
voidError(char*s);/*自定义错误处理函数*/
voidpntList(LinkListhead);/*打印单链表*/
voidsave(LinkListhead,charstrname[]);/*保存单链表到文件*/
任务一
创建程序文件linklist.cpp,其代码如下所示,理解LinkList类型和基本运算函数后回答下列问题。
#include
#include
/*单链表结点类型*/
typedefstruct{
intxh;/*学号*/
floatsg;/*身高*/
intsex;/*性别,0为男生,1为女生*/
}datatype;
typedefstructnode{
datatypedata;/*数据域*/
structnode*next;/*指针域*/
}LinkNode,*LinkList;
/*带表头的单链表的基本运算函数*/
LinkListinitList();/*置一个空表(带头结点)*/
voidcreateList_1(LinkListhead);/*创建单链表*/
voidcreateList_2(LinkListhead);/*创建单链表*/
voidsort_xh(LinkListhead);/*单链表排序*/
voidreverse(LinkListhead);/*单链表倒置*/
voidError(char*s);/*自定义错误处理函数*/
voidpntList(LinkListhead);/*打印单链表*/
voidsave(LinkListhead,charstrname[]);/*保存单链表到文件*/
/*置一个空表*/
LinkListinitList()
{LinkListp;
p=(LinkList)malloc(sizeof(LinkNode));
p->next=NULL;
returnp;
}
/*创建单链表*/
voidcreateList_1(LinkListhead)
{FILE*fp;
intxh;
floatsg;
intsex;
LinkListp;
if((fp=fopen("records.txt","r"))==NULL)
{Error("cannotopenfile!
");
return;
}
while(!
feof(fp))
{fscanf(fp,"%d%f%d",&xh,&sg,&sex);
p=(LinkList)malloc(sizeof(LinkNode));
p->data.xh=xh;
p->data.sg=sg;
p->data.sex=sex;
p->next=head->next;
head->next=p;
}
fclose(fp);
}
/*创建单链表*/
voidcreateList_2(LinkListhead)
{FILE*fp;
intxh;
floatsg;
intsex;
LinkListp,rear;
if((fp=fopen("records.txt","r"))==NULL)
{Error("cannotopenfile!
");
return;
}
rear=head;
while(!
feof(fp))
{fscanf(fp,"%d%f%d",&xh,&sg,&sex);
p=(LinkList)malloc(sizeof(LinkNode));
p->data.xh=xh;
p->data.sg=sg;
p->data.sex=sex;
p->next=NULL;
rear->next=p;
rear=p;
}
fclose(fp);
}
/*单链表排序*/
voidsort_xh(LinkListhead)
{
LinkListq,p,u;
p=head->next;
head->next=NULL;/*利用原表头结点建新的空表*/
while(p)
{q=p;/*q为被插入的结点*/
p=p->next;/*用p记录后继结点*/
/*遍历新链表查找插入位置*/
u=head;
while(u->next!
=NULL)/*查找插入位置*/
{if(u->next->data.xh>q->data.xh)
break;
u=u->next;
}
/*插入在u结点的后面*/
q->next=u->next;
u->next=q;
}
}
/*单链表倒置*/
voidreverse(LinkListhead)
{LinkListp,r;
p=head->next;
head->next=NULL;
while(p)
{r=p;
p=p->next;
/*r指向结点头插到链表*/
r->next=head->next;
head->next=r;
}
}
/*输出单链表*/
voidpntList(LinkListhead)
{LinkListp;
p=head->next;
while(p!
=NULL)
{printf("%2d:
%.2f%d\n",p->data.xh,p->data.sg,p->data.sex);
p=p->next;
}
}
/*自定义错误处理函数*/
voidError(char*s)
{printf("\n%s",s);
exit
(1);/*返回OS,该函数定义在stdlib.h中*/
}
/*保存单链表到文件*/
voidsave(LinkListhead,charstrname[])
{FILE*fp;
LinkListp;
if((fp=fopen(strname,"w"))==NULL)
{printf("cannotopenfile!
");
return;
}
p=head->next;
while(p!
=NULL)
{fprintf(fp,"%2d%5.2f%2d\n",p->data.xh,p->data.sg,p->data.sex);
p=p->next;
}
fclose(fp);
}
请回答下列问题:
(1)由单链表结点类型定义可知,该链表结点类型名为LinkNode,结点的指针类型为LinkList,向系统申请一个学生结点空间并把起始地址存于上述结点指针变量new中的语句是:
p=(LinkList)malloc(sizeof(LinkNode));。
(2)回答问题:
a)已知:
LinkListhead;画出执行head=initList();语句后的链表结构示意图
head
*顺序:
1-13-7-15-2
p
b)在a)操作的基础上,根据records.txt中的数据,画出执行createList_1(head);语句后的链表结构示意图
head
c)在b)操作的基础上,画出执行sort_xh(head);语句后的链表结构示意图
head
d)在c)操作的基础上,画出执行reverse(head);语句后的链表结构示意图
head
e)在d)操作的基础上,写出执行pntList(head);语句后屏幕输出结果
(3)写出下列操作对应的执行语句(以下的指针变量的类型都是上述定义的结点指针类型)
a)把一个new指针指向的结点头插到以h为头指针带表头结点的单链表中的语句
new->next=h->next;
h->next=new;
b)把一个new指针指向的结点头插到以h为头指针不带表头结点的单链表中的语句
new->next=h;
h=new;
c)在单链表中删除r所指结点的后继结点(假设存在)的语句
r->next=r->next->next
d)分别写出循环及非循环单链表中判断r所指结点是尾结点(假设存在)的条件
循环:
r->next==NULL
非循环:
r->next!
=NULL
任务二
1.题目要求
创建一个新的程序文件sy12.cpp,请调用linklist.cpp提供的功能函数(以#include“linklist.cpp”方式导入函数库)及自定义的函数完成以下操作:
●从数据文件records.txt中读取学生信息,建立与源数据同序的学生链表并打印在屏幕上;
●统计学生链表中身高达标人数(男女生的身高达标值由键盘输入),并打印结果;
●从键盘输入一位学生的相关信息插入到已排序的学生身高链表中后仍然保持学号的有序性;
●对上述操作后的学生链表进行倒置,结果输出到数据文件result.txt中;
●删除链表中身高为指定值的所有学生结点并打印;
在程序文件sy12.cpp需再定义以下三个功能函数:
(1)intcount(LinkListhead,floatsg_fm,floatsg_m)
功能:
已知女生达标身高为sg_fm,男生达标身高为sg_m,统计head为头指针的学生链表中身高达标人数并返回;
(2)voidinsertX(LinkListhead,datatypex)
功能:
在学号从小到大排序的学生链表中插入值为x的学生仍保持学号的有序性
(3)intdelete(LinkListhead,floatsg)
功能:
删除head为头指针的学生链表中指定身高的所有学生结点,删除成功返回1,否则返回0;
2.请根据题目功能要求或程序中的注释完整sy12.cpp代码
#include"linklist.cpp"
intcount(LinkListhead,floatsg_fm,floatsg_m);/*统计head为头指针的学生链表中身高达标人数并返回*/
voidinsertX(LinkListhead,datatypex);/*在学号从小到大排序的学生链表中插入值为x的学生仍保持学号的有序性*/
intdelete(LinkListhead,floatsg);/*删除head为头指针的学生链表中指定身高的所有学生结点,删除成功返回1,否则返回0*/
voidmain()
{LinkListhead;
intc,flag;
floatsg,sg_fm,sg_m;
datatypex;
/*建立与源数据文件同序的学生链表并输出;*/
head=initList();/*建空链表*/
createList_2(head);/*调用建链表函数建立所需链表*/
printf("\n与数据文件同序的学生链表:
\n");
pntList(head);/*调用函数打印输出链表中信息*/
getchar();
/*统计学生链表中身高达标人数(男女生的身高达标值由键盘输入)并打印结果;*/
printf("\n输入达标的女生、男生身高值:
");
scanf("%f%f",&sg_fm,&sg_m);
c=count(head,sg_fm,sg_m);
printf("\n达标学生人数为:
%d",c);
getchar();
/*对学生链表按学号进行排序*/
sort_xh(head);
/*在学生链表中插入指定的学生元素后使链表仍按学号有序*/
x.xh=3;
x.sg=1.67;
x.sex=0;
insertX(head,x);
printf("\nnewlistafterinsert:
\n");
pntList(head);
getchar();
/*对学生链表进行倒置,结果输出到文件result.txt中;*/
reverse(head);
save(head,"result.txt");
getchar();
/*删除链表中身高为指定值的所有学生结点;*/
sg=1.67;
flag=dele(head,sg);
if(flag)
printf("\ndeletesucceed!
\n");
else
printf("\ndeletefailed\n");
printf("\nnewlistafterdelete:
\n");
pntList(head);
getchar();
}
//统计学生链表中身高达标人数并返回(sg_fm女生身高达标值、sg_m男生身高达标值)
intcount(LinkListhead,floatsg_fm,floatsg_m)
{intn=0;
LinkListp;
p=head->next;
while(p!
=NULL)
{
if(p->data.sex==1)/*sex:
1女生*/
{
if(p->data.sg>=sg_fm)
n++;
}
else
{
if(p->data.sg>=sg_m)
n++;
}
p=p->next;
}
returnn;
}
//在学号从小到大排序的学生链表中插入值为x的学生仍保持学号的有序性
voidinsertX(LinkListhead,datatypex)
{
LinkListp,u;
p=(LinkList)malloc(sizeof(LinkNode));
p->data.xh=x.xh;
p->data.sg=x.sg;
p->data.sex=x.sex;
u=head;
while(u->next!
=NULL)
{
if(u->next->data.xh>x.xh)
break;
u=u->next;
}
p->next=u->next;
u->next=p;
}
//删除学生链表中指定身高(存于sg中)的所有学生结点,删除成功返回1,否则返回0
intdelete(LinkListhead,floatsg)
{
LinkListp,q,v;
intflag=0;
q=head;
p=head->next;
while(p!
=NULL)
{
if(p->data.sg==sg)
{/*删除p所指结点*/
v=p;
p=p->next;
q->next=p;
free(v);
flag=1;
}
else
{
q=p;
p=p->next;
}
}
returnflag;/*删除成功返回1,否则返回0*/
}
实验总结分析(本程序的重点与难点,调试中出现的问题及解决方法等)