单链表操作验证 验证型.docx
- 文档编号:6370576
- 上传时间:2023-01-05
- 格式:DOCX
- 页数:15
- 大小:39.74KB
单链表操作验证 验证型.docx
《单链表操作验证 验证型.docx》由会员分享,可在线阅读,更多相关《单链表操作验证 验证型.docx(15页珍藏版)》请在冰豆网上搜索。
单链表操作验证验证型
实验报告
课程名称数据结构
实验名称单链表实验验证
实验类型验证型
实验地点计405机房实验日期2017.4.28
指导教师魏海平
专业软件工程
班级软件1601
学号1611030102
姓名寇春雷
辽宁石油化工大学计算机与通信工程学院
数据结构实验报告评分表
项目
要求
分数
有无项目(√)
得分
预习报告
(30分)
实验目的明确
5
实验内容理解透彻
5
实验方案设计完整合理
程序总体框架设计完整
10
完成相关辅助代码
5
测试方案合理
5
实验过程
(30分)
发现问题
5
问题的分析
15
问题的解决方法
10
实验报告
(20分)
内容翔实无缺漏
5
如实记录实验过程
10
撰写规整
5
实验总结
(10分)
实验结果的分析
5
按照结果对原实验方案的改进意见
5
实验体会
(10分)
实验的收获
5
实验内容的发散考虑
5
总分
一.问题描述:
1.实验题目
单链表操作验证。
2.实验目的
(1)掌握线性表的链接存储结构。
(2)验证单链表及其基本操作的实现。
(3)进一步掌握数据结构及算法的程序实现的基本方法。
3.实验内容的理解
(1)用头插法(或尾插法)建立带头结点的单链表。
(2)对已建立的单链表实现按给定值和按序号对单链表进行插人、删除、查找和置逆等基本操作。
(3)对单链表进行初始化,建立带头节点的单链表,将单链表按其值非递归排序等操作。
4.实验要求
(1)采用标准C语言实现。
(2)对单链表操作前和操作后都要输出链表的内容。
(3)对要进行的操作有必要的提示信息。
(4)对实现的功能采用菜单的形式进行展示和选择。
二.设计
1.数据结构设计和核心算法设计描述。
2.主控及功能模块层次结构。
3.主要功能模块。
(1)主程序模块:
void main(){
初始化;
正序、逆序输出链表;
合并链表;
}
(2)集合单元模块——实现集合的抽象数据类型;
(3)单链表单元模块——实现单链表的抽象数据类型;
(4)结点结构单元模块——定义链表的结点结构;
4.功能模块之间的调用与被调用关系:
主程序模块
集合单元模块
单链表单元模块
结点结构单元模块
三.测试
(1)程序运行截图
(2)程序源码
#include"stdafx.h"
/*第一部包括必要的头函数并定义状态值*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*函数结果状态代码*/
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
/*#defineOVERFLOW-2因为在math.h中已定义OVERFLOW的值为3,故去掉此行*/
typedefintStatus;/*Status是函数的类型,其值是函数结果状态代码,如OK等*/
typedefintBoolean;/*Boolean是布尔类型,其值是TRUE或FALSE*/
typedefintElemType;
/*第二部定义线性表的单链表存储结构*/
typedefstructLNode
{
ElemTypedata;
structLNode*next;
}LNode;
typedefstructLNode*LinkList;/*另一种定义LinkList的方法*/
/*第三部带有头结点的单链表(存储结构如上定义)的基本操作(12个)*/
voidInitList(LinkListL)
{/*操作结果:
构造一个空的线性表L*/
L=(LinkList)malloc(sizeof(LNode));/*产生头结点,并使L指向此头结点*/
if(!
L)/*存储分配失败*/
exit(OVERFLOW);
L->next=NULL;/*指针域为空*/
}
voidDestroyList(LinkListL)
{/*初始条件:
线性表L已存在。
操作结果:
销毁线性表L*/
LinkListq;
while(L)
{
q=L->next;
free(L);
L=q;
}
}
voidClearList(LinkListL)/*不改变L*/
{/*初始条件:
线性表L已存在。
操作结果:
将L重置为空表*/
LinkListp,q;
p=L->next;/*p指向第一个结点*/
while(p)/*没到表尾*/
{
q=p->next;
free(p);
p=q;
}
L->next=NULL;/*头结点指针域为空*/
}
StatusListEmpty(LinkListL)
{/*初始条件:
线性表L已存在。
操作结果:
若L为空表,则返回TRUE,否则返回FALSE*/
if(L->next)/*非空*/
returnFALSE;
else
returnTRUE;
}
intListLength(LinkListL)
{/*初始条件:
线性表L已存在。
操作结果:
返回L中数据元素个数*/
inti=0;
LinkListp=L->next;/*p指向第一个结点*/
while(p)/*没到表尾*/
{
i++;
p=p->next;
}
returni;
}
StatusGetElem(LinkListL,inti,ElemType*e)/*算法2.8*/
{/*L为带头结点的单链表的头指针。
当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR*/
intj=1;/*j为计数器*/
LinkListp=L->next;/*p指向第一个结点*/
while(p&&j
{
p=p->next;
j++;
}
if(!
p||j>i)/*第i个元素不存在*/
returnERROR;
*e=p->data;/*取第i个元素*/
returnOK;
}
intLocateElem(LinkListL,ElemTypee,Status(*compare)(ElemType,ElemType)){/*初始条件:
线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0)*/
/*操作结果:
返回L中第1个与e满足关系compare()的数据元素的位序*/
/*若这样的数据元素不存在,则返回值为0*/
inti=1;
LinkListp=L->next;
while(p)
{
i++;
if(compare(p->data,e))/*找到这样的数据元素*/
returni;
p=p->next;
}
return0;
}
StatusPriorElem(LinkListL,ElemTypecur_e,ElemType*pre_e)
{/*初始条件:
线性表L已存在*/
/*操作结果:
若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,*/
/*返回OK;否则操作失败,pre_e无定义,返回INFEASIBLE*/
LinkListq,p=L->next;/*p指向第一个结点*/
while(p->next)/*p所指结点有后继*/
{
q=p->next;/*q为p的后继*/
if(q->data==cur_e){
*pre_e=p->data;
returnOK;
}
p=q;/*p向后移*/
}
returnINFEASIBLE;
}
StatusNextElem(LinkListL,ElemTypecur_e,ElemType*next_e)
{/*初始条件:
线性表L已存在*/
/*操作结果:
若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后*/
/*返回OK;否则操作失败,next_e无定义,返回INFEASIBLE*/
LinkListp=L->next;/*p指向第一个结点*/
while(p->next)/*p所指结点有后继*/
{
if(p->data==cur_e){
*next_e=p->next->data;
returnOK;
}
p=p->next;
}
returnINFEASIBLE;
}
StatusListInsert(LinkListL,inti,ElemTypee)/*算法2.9。
不改变L*/
{/*在带头结点的单链线性表L中第i个位置之前插入元素e*/
intj=0;
LinkListp=L,s;
while(p&&j { p=p->next; j++; } if(! p||j>i-1)/*i小于1或者大于表长*/ returnERROR; s=(LinkList)malloc(sizeof(structLNode));/*生成新结点*/ s->data=e;/*插入L中*/ s->next=p->next; p->next=s; returnOK; } StatusListDelete(LinkListL,inti,ElemType*e)/*算法2.10。 不改变L*/ {/*在带头结点的单链线性表L中,删除第i个元素,并由e返回其值*/ intj=0; LinkListp=L,q; while(p->next&&j { p=p->next; j++; } if(! p->next||j>i-1)/*删除位置不合理*/ returnERROR; q=p->next;/*删除并释放结点*/ p->next=q->next; *e=q->data; free(q); returnOK; } voidListTraverse(LinkListL,void(*vi)(ElemType)) /*vi的形参类型为ElemType*/ {/*初始条件: 线性表L已存在。 操作结果: 依次对L的每个数据元素调用函数vi()*/ LinkListp=L->next; while(p){ vi(p->data); p=p->next; } printf("\n"); } /*第四部定义了几个常用函数equal()、comp()、print()、print2()和print1()函数*/ Statusequal(ElemTypec1,ElemTypec2){/*判断是否相等的函数*/ if(c1==c2)returnTRUE; elsereturnFALSE; } intcomp(ElemTypea,ElemTypeb){/*根据a<、=或>b,分别返回-1、0或1*/ if(a==b)return0; elsereturn(a-b)/abs(a-b); } voidprint(ElemTypec){ printf("%d",c); } voidprint2(ElemTypec){ printf("%c",c); } voidprint1(ElemType*c){ printf("%d",*c); } voidCreateList(LinkList*L,intn)/*算法2.11*/ {/*逆位序(插在表头)输入n个元素的值,建立带表头结构的单链线性表L*/ inti; LinkListp; *L=(LinkList)malloc(sizeof(structLNode)); (*L)->next=NULL;/*先建立一个带头结点的单链表*/ printf("请输入%d个数据\n",n); for(i=n;i>0;--i){ p=(LinkList)malloc(sizeof(structLNode));/*生成新结点*/ Scanf_s("%d",&p->data);/*输入元素值*/ p->next=(*L)->next;/*插入到表头*/ (*L)->next=p; } } voidCreateList2(LinkList*L,intn) {/*正位序(插在表尾)输入n个元素的值,建立带表头结构的单链线性表L*/ inti; LinkListp,q; *L=(LinkList)malloc(sizeof(structLNode));/*生成头结点*/ (*L)->next=NULL; q=*L; printf("请输入%d个数据\n",n); for(i=1;i<=n;i++){ p=(LinkList)malloc(sizeof(structLNode)); Scanf_s("%d",&p->data); q->next=p; q=q->next; } p->next=NULL; } voidMergeList(LinkListLa,LinkList*Lb,LinkList*Lc)/*算法2.12*/ {/*已知单链线性表La和Lb的元素按值非递减排列。 */ /*归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列*/ LinkListpa=La->next,pb=(*Lb)->next,pc; *Lc=pc=La;/*用La的头结点作为Lc的头结点*/ while(pa&&pb) if(pa->data<=pb->data){ pc->next=pa; pc=pa; pa=pa->next; } else{ pc->next=pb; pc=pb; pb=pb->next; } pc->next=pa? pa: pb;/*插入剩余段*/ free(*Lb);/*释放Lb的头结点*/ Lb=NULL; } voidmain() { intn=5; LinkListLa,Lb,Lc; printf("按非递减顺序(正位序建立单链表括"); CreateList2(&La,n);/*正位序输入n个元素的值*/ printf("La=");/*输出链表的内容*/ ListTraverse(La,print); printf("按非递增顺序(逆位序建立单链表"); CreateList(&Lb,n);/*逆位序输入n个元素的值*/ printf("Lb=");/*输出链表的内容*/ ListTraverse(Lb,print); MergeList(La,&Lb,&Lc);/*按非递减顺序归并La和Lb,得到新表Lc*/ printf("Lc=");/*输出链表括Lc的容*/ printf("La和Lb非递减顺序为Lc: \n"); ListTraverse(Lc,print); printf("Lc单链表的长度为: "); printf("%d\n",ListLength(Lc)); printf("在Lc单链表的第i个位置前插入元素e: \n请输入元素e="); inte; scanf("%d",&e); printf("请输入位置i="); inti; scanf("%d",&i); ListInsert(Lc,i,e); printf("Lc="); ListTraverse(Lc,print); printf("将Lc置为空表\n"); ClearList(Lc); printf("Lc="); ListTraverse(Lc,print); } (3)实验过程发现的问题 ①.在voidCreateList2(LinkList*L,intn)函数中Scanf("%d",&p->data);输入方式不安全 ②.在voidCreateList(LinkList*L,intn)函数中Scanf_s("%d",&p->data);输入方式不安全 ③.在intLocateElem(LinkListL,ElemTypee,Status(*compare)(ElemType,ElemType))函数中 i=0;LinkListp=L->next;逻辑错误 (4)问题分析及解决方案 ①.在voidCreateList2(LinkList*L,intn)函数中改为 Scanf_s("%d",&p->data); ②.在voidCreateList(LinkList*L,intn)函数中改为 Scanf_s("%d",&p->data); ③.在intLocateElem(LinkListL,ElemTypee,Status(*compare)(ElemType,ElemType))函数中 将i=0;改为i=1;或将LinkListp=L->next;改为LinkListp=L->next->next; p指向第一节点。 四.实验结果分析 除了scanf();函数出错外,intLocateElem(LinkListL,ElemTypee,Status(*compare)(ElemType,ElemType))函数中有逻辑错误,其他函数测试正常。 五.作业小结 (1)StatusListInsert(LinkListL,inti,ElemTypee)中 ①.插入新数据只该元素的地址 ②.转移原指针 ③.拼接新指针 (2)在StatusGetElem(LinkListL,inti,Elemtype*e)中 P=L->next;j=1;while();查找元素时,如果第i个元素不存在,则返回ERROR (3)在voidCreateList(LinkList*L,intn)中 P->next=L->next;L->next=p; ①转移指针。 ②连接指针。 (4)在MergeList(LinkListLa,LinkList*Lb,LinkList*Lc)中 La,Lb为非空表时,pa和pb分别指向表中的第一个结点。 第一个循环条件是Pa,pb都不为空。 六.对原方案的改进意见 intLocateElem(LinkListL,ElemTypee,Status(*compare)(ElemType,ElemType)){若这样的数据元素不存在,则返回值为0*/ inti=1; LinkListp=L->next; while(p) { i++; if(compare(p->data,e))/*找到这样的数据元素*/ returni; p=p->next; } return0; } 或者i=0;LinkListp=L->next->next; 七.实验收获 (1)通过此实验我对单链表进行初始化,建立带头节点的单链表,将单链表按其值非递归排序等操作有了进一步的了解。 (2)再进行插入,删除等操作时,单链表由于顺序表。 (3)对验证实验有了进一步的了解。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单链表操作验证 验证型 单链表 操作 验证