1、单链表操作验证 验证型实 验 报 告课程名称 数据结构 实验名称 单链表实验验证 实验类型 验证型 实验地点 计405机房 实验日期 2017.4.28指导教师 魏海平 专业 软件工程 班级 软件1601 学号 1611030102 姓名 寇春雷 辽宁石油化工大学计算机与通信工程学院数据结构实验报告评分表项目要求分数有无项目()得分预习报告(30分)实验目的明确5实验内容理解透彻5实验方案设计完整合理程序总体框架设计完整10完成相关辅助代码5测试方案合理5实验过程(30分)发现问题5问题的分析15问题的解决方法10实验报告(20分)内容翔实无缺漏5如实记录实验过程10撰写规整5实验总结(10分
2、)实验结果的分析5按照结果对原实验方案的改进意见5实验体会(10分)实验的收获5实验内容的发散考虑5总分一问题描述:1.实验题目单链表操作验证。2实验目的(1)掌握线性表的链接存储结构。(2)验证单链表及其基本操作的实现。(3)进一步掌握数据结构及算法的程序实现的基本方法。3实验内容的理解(1)用头插法(或尾插法)建立带头结点的单链表。(2)对已建立的单链表实现按给定值和按序号对单链表进行插人、删除、查找和置逆等基本操作。(3)对单链表进行初始化,建立带头节点的单链表,将单链表按其值非递归排序等操作。4实验要求(1)采用标准C语言实现。(2)对单链表操作前和操作后都要输出链表的内容。(3)对要
3、进行的操作有必要的提示信息。(4)对实现的功能采用菜单的形式进行展示和选择。二设计1.数据结构设计和核心算法设计描述。2.主控及功能模块层次结构。 3.主要功能模块。 (1)主程序模块: voidmain() 初始化; 正序、逆序输出链表; 合并链表; (2)集合单元模块实现集合的抽象数据类型; (3)单链表单元模块实现单链表的抽象数据类型; (4)结点结构单元模块定义链表的结点结构;.功能模块之间的调用与被调用关系:主程序模块集合单元模块单链表单元模块结点结构单元模块三测试(1)程序运行截图(2)程序源码#includestdafx.h/*第一部 包括必要的头函数并定义状态值 */ #inc
4、lude #include #include /* malloc()等 */ #include /* INT_MAX等 */ #include /* EOF(=Z或F6),NULL */NULL scanf();printf(); #include #include /* eof() */ #include #include /* exit() */ /* 函数结果状态代码 */ #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 /* #define OVERFLOW -2 因为在
5、math.h中已定义OVERFLOW的值为3,故去掉此行 */ typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */ typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */ typedef int ElemType;/*第二部 定义线性表的单链表存储结构*/ typedef struct LNode ElemType data; struct LNode *next; LNode; typedef struct LNode *LinkList; /* 另一种定义LinkList的方法
6、*/*第三部 带有头结点的单链表(存储结构如上定义)的基本操作(12个) */ void InitList(LinkList L) /* 操作结果:构造一个空的线性表L */ L=(LinkList)malloc(sizeof(LNode); /* 产生头结点,并使L指向此头结点 */ if(!L) /* 存储分配失败 */ exit(OVERFLOW); L-next=NULL; /* 指针域为空 */ void DestroyList(LinkList L) /* 初始条件:线性表L已存在。操作结果:销毁线性表L */ LinkList q; while(L) q=L-next; free
7、(L); L=q; void ClearList(LinkList L) /* 不改变L */ /* 初始条件:线性表L已存在。操作结果:将L重置为空表 */ LinkList p,q; p=L-next; /* p指向第一个结点 */ while(p) /* 没到表尾 */ q=p-next; free(p); p=q; L-next=NULL; /* 头结点指针域为空 */ Status ListEmpty(LinkList L) /* 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */ if(L-next) /* 非空 */ return FALSE
8、; else return TRUE; int ListLength(LinkList L) /* 初始条件:线性表L已存在。操作结果:返回L中数据元素个数 */ int i=0; LinkList p=L-next; /* p指向第一个结点 */ while(p) /* 没到表尾 */ i+; p=p-next; return i; Status GetElem(LinkList L,int i,ElemType *e) /* 算法2.8 */ /* L为带头结点的单链表的头指针。当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */ int j=1; /* j为计数器 */ L
9、inkList p=L-next; /* p指向第一个结点 */ while(p&jnext; j+; if(!p|ji) /* 第i个元素不存在 */ return ERROR; *e=p-data; /* 取第i个元素 */ return OK; int LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType) /* 初始条件: 线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0) */ /* 操作结果: 返回L中第1个与e满足关系compare()的数据元素的位序*/ /* 若这样的数据
10、元素不存在,则返回值为0 */ int i=1; LinkList p=L-next; while(p) i+; if(compare(p-data,e) /* 找到这样的数据元素 */ return i; p=p-next; return 0; Status PriorElem(LinkList L,ElemType cur_e,ElemType *pre_e) /* 初始条件: 线性表L已存在 */ /* 操作结果: 若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, */ /* 返回OK;否则操作失败,pre_e无定义,返回INFEASIBLE */ LinkList
11、 q,p=L-next; /* p指向第一个结点 */ while(p-next) /* p所指结点有后继 */ q=p-next; /* q为p的后继 */ if(q-data=cur_e) *pre_e=p-data; return OK; p=q; /* p向后移 */ return INFEASIBLE; Status NextElem(LinkList L,ElemType cur_e,ElemType *next_e) /* 初始条件:线性表L已存在 */ /* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后*/ /* 返回OK;否则操作失败,ne
12、xt_e无定义,返回INFEASIBLE */ LinkList p=L-next; /* p指向第一个结点 */ while(p-next) /* p所指结点有后继 */ if(p-data=cur_e) *next_e=p-next-data; return OK; p=p-next; return INFEASIBLE; Status ListInsert(LinkList L,int i,ElemType e) /* 算法2.9。不改变L */ /* 在带头结点的单链线性表L中第i个位置之前插入元素e */ int j=0; LinkList p=L,s; while(p&jnext;
13、 j+; if(!p|ji-1) /* i小于1或者大于表长 */ return ERROR; s=(LinkList)malloc(sizeof(struct LNode); /* 生成新结点 */ s-data=e; /* 插入L中 */ s-next=p-next; p-next=s; return OK; Status ListDelete(LinkList L,int i,ElemType *e) /* 算法2.10。不改变L */ /* 在带头结点的单链线性表L中,删除第i个元素,并由e返回其值 */ int j=0; LinkList p=L,q; while(p-next&jn
14、ext; j+; if(!p-next|ji-1) /* 删除位置不合理 */ return ERROR; q=p-next; /* 删除并释放结点 */ p-next=q-next; *e=q-data; free(q); return OK; void ListTraverse(LinkList L,void(*vi)(ElemType) /* vi的形参类型为ElemType*/ /* 初始条件:线性表L已存在。操作结果:依次对L的每个数据元素调用函数vi() */ LinkList p=L-next; while(p) vi(p-data); p=p-next; printf(n);
15、/*第四部 定义了几个常用函数equal()、comp()、print()、print2()和print1()函数 */ Status equal(ElemType c1,ElemType c2) /* 判断是否相等的函数 */ if(c1=c2) return TRUE; else return FALSE; int comp(ElemType a,ElemType b) /* 根据ab,分别返回-1、0或1 */ if(a=b) return 0; else return (a-b)/abs(a-b); void print(ElemType c) printf(%d ,c); void
16、print2(ElemType c) printf(%c ,c); void print1(ElemType *c) printf(%d ,*c); void CreateList(LinkList *L,int n) /* 算法2.11 */ /* 逆位序(插在表头)输入n个元素的值,建立带表头结构的单链线性表L */ int i; LinkList p; *L=(LinkList)malloc(sizeof(struct LNode); (*L)-next=NULL; /* 先建立一个带头结点的单链表 */ printf(请输入%d个数据n,n); for(i=n;i0;-i) p=(Li
17、nkList)malloc(sizeof(struct LNode); /* 生成新结点 */ Scanf_s(%d,&p-data); /* 输入元素值 */ p-next=(*L)-next; /* 插入到表头 */ (*L)-next=p; void CreateList2(LinkList *L,int n) /* 正位序(插在表尾)输入n个元素的值,建立带表头结构的单链线性表L */ int i; LinkList p,q; *L=(LinkList)malloc(sizeof(struct LNode); /* 生成头结点 */ (*L)-next=NULL; q=*L; prin
18、tf(请输入%d个数据n,n); for(i=1;idata); q-next=p; q=q-next; p-next=NULL; void MergeList(LinkList La,LinkList *Lb,LinkList *Lc) /* 算法2.12 */ /* 已知单链线性表La和Lb的元素按值非递减排列。 */ /* 归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列 */ LinkList pa=La-next,pb=(*Lb)-next,pc; *Lc=pc=La; /* 用La的头结点作为Lc的头结点 */ while(pa&pb) if(pa-datadata
19、) 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; void main() int n=5; LinkList La,Lb,Lc; printf(按非递减顺序(正位序建立单链表括 ); CreateList2(&La,n); /* 正位序输入n个元素的值 */ printf(La=); /* 输出链表的内容*/ ListTraverse(La,print); printf(按非递增
20、顺序(逆位序建立单链表); 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(%dn,ListLength(Lc); printf(在Lc单链表的第i个位置前插入元
21、素e:n请输入元素e=); int e; scanf(%d,&e); printf(请输入位置i=); int i; scanf(%d,&i); ListInsert(Lc,i,e); printf(Lc=); ListTraverse(Lc,print); printf(将Lc置为空表n); ClearList(Lc); printf(Lc=); ListTraverse(Lc,print); (3)实验过程发现的问题在void CreateList2(LinkList *L,int n)函数中Scanf(%d,&p-data);输入方式不安全在void CreateList(LinkLis
22、t *L,int n) 函数中Scanf_s(%d,&p-data); 输入方式不安全在int LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType)函数中i=0;LinkList p=L-next;逻辑错误(4)问题分析及解决方案在void CreateList2(LinkList *L,int n)函数中改为Scanf_s(%d,&p-data);在void CreateList(LinkList *L,int n) 函数中改为Scanf_s(%d,&p-data); 在int LocateElem(Link
23、List L,ElemType e,Status(*compare)(ElemType,ElemType)函数中将i=0;改为i=1;或将LinkList p=L-next;改为LinkList p=L-next-next;p指向第一节点。四实验结果分析除了scanf();函数出错外,int LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType)函数中有逻辑错误,其他函数测试正常。五作业小结(1) Status ListInsert(LinkList L,int i,ElemType e)中插入新数据只该元素的地
24、址转移原指针拼接新指针(2)在Status GetElem(LinkList L,int i,Elemtype *e)中P=L-next;j=1;while();查找元素时,如果第i个元素不存在,则返回ERROR(3)在void CreateList(LinkList *L,int n)中P-next=L-next;L-next=p;转移指针。连接指针。(4)在MergeList(LinkList La,LinkList *Lb,LinkList *Lc)中La,Lb为非空表时,pa和pb分别指向表中的第一个结点。第一个循环条件是Pa,pb都不为空。六对原方案的改进意见int LocateEl
25、em(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType) 若这样的数据元素不存在,则返回值为0 */ int i=1; LinkList p=L-next; while(p) i+; if(compare(p-data,e) /* 找到这样的数据元素 */ return i; p=p-next; return 0; 或者i=0;LinkList p=L-next-next;七实验收获(1)通过此实验我对单链表进行初始化,建立带头节点的单链表,将单链表按其值非递归排序等操作有了 进一步的了解。(2)再进行插入,删除等操作时,单链表由于顺序表。(3)对验证实验有了进一步的了解。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1