单链表操作验证 验证型Word格式.docx
《单链表操作验证 验证型Word格式.docx》由会员分享,可在线阅读,更多相关《单链表操作验证 验证型Word格式.docx(15页珍藏版)》请在冰豆网上搜索。
按照结果对原实验方案的改进意见
实验体会
实验的收获
实验内容的发散考虑
总分
一.问题描述:
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<
string.h>
ctype.h>
malloc.h>
/*malloc()等*/
limits.h>
/*INT_MAX等*/
stdio.h>
/*EOF(=^Z或F6),NULL*/NULLscanf();
printf();
stdlib.h>
io.h>
/*eof()*/
math.h>
process.h>
/*exit()*/
/*函数结果状态代码*/
#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重置为空表*/
LinkListp,q;
p=L->
/*p指向第一个结点*/
while(p)/*没到表尾*/
q=p->
free(p);
p=q;
/*头结点指针域为空*/
StatusListEmpty(LinkListL)
若L为空表,则返回TRUE,否则返回FALSE*/
if(L->
next)/*非空*/
returnFALSE;
else
returnTRUE;
intListLength(LinkListL)
返回L中数据元素个数*/
inti=0;
LinkListp=L->
i++;
p=p->
returni;
StatusGetElem(LinkListL,inti,ElemType*e)/*算法2.8*/
{/*L为带头结点的单链表的头指针。
当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR*/
intj=1;
/*j为计数器*/
while(p&
&
j<
i)/*顺指针向后查找,直到p指向第i个元素或p为空*/
j++;
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;
while(p)
if(compare(p->
data,e))/*找到这样的数据元素*/
return0;
StatusPriorElem(LinkListL,ElemTypecur_e,ElemType*pre_e)
{/*初始条件:
线性表L已存在*/
若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,*/
/*返回OK;
否则操作失败,pre_e无定义,返回INFEASIBLE*/
LinkListq,p=L->
while(p->
next)/*p所指结点有后继*/
/*q为p的后继*/
if(q->
data==cur_e){
*pre_e=p->
/*p向后移*/
returnINFEASIBLE;
StatusNextElem(LinkListL,ElemTypecur_e,ElemType*next_e)
线性表L已存在*/
/*操作结果:
若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后*/
/*返回OK;
否则操作失败,next_e无定义,返回INFEASIBLE*/
if(p->
*next_e=p->
next->
StatusListInsert(LinkListL,inti,ElemTypee)/*算法2.9。
不改变L*/
{/*在带头结点的单链线性表L中第i个位置之前插入元素e*/
intj=0;
LinkListp=L,s;
i-1)/*寻找第i-1个结点*/
i-1)/*i小于1或者大于表长*/
s=(LinkList)malloc(sizeof(structLNode));
/*生成新结点*/
s->
data=e;
/*插入L中*/
next=p->
p->
next=s;
StatusListDelete(LinkListL,inti,ElemType*e)/*算法2.10。
{/*在带头结点的单链线性表L中,删除第i个元素,并由e返回其值*/
LinkListp=L,q;
next&
i-1)/*寻找第i个结点,并令p指向其前岖*/
p->
next||j>
i-1)/*删除位置不合理*/
/*删除并释放结点*/
next=q->
*e=q->
free(q);
voidListTraverse(LinkListL,void(*vi)(ElemType))
/*vi的形参类型为ElemType*/
依次对L的每个数据元素调用函数vi()*/
while(p){
vi(p->
data);
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){
%d"
c);
voidprint2(ElemTypec){
%c"
voidprint1(ElemType*c){
*c);
voidCreateList(LinkList*L,intn)/*算法2.11*/
{/*逆位序(插在表头)输入n个元素的值,建立带表头结构的单链线性表L*/
inti;
LinkListp;
*L=(LinkList)malloc(sizeof(structLNode));
(*L)->
/*先建立一个带头结点的单链表*/
请输入%d个数据\n"
n);
for(i=n;
i>
0;
--i){
p=(LinkList)malloc(sizeof(structLNode));
Scanf_s("
%d"
&
/*输入元素值*/
next=(*L)->
/*插入到表头*/
next=p;
voidCreateList2(LinkList*L,intn)
{/*正位序(插在表尾)输入n个元素的值,建立带表头结构的单链线性表L*/
/*生成头结点*/
q=*L;
for(i=1;
i<
=n;
i++){
q->
q=q->
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->
else{
next=pb;
pc=pb;
pb=pb->
next=pa?
pa:
pb;
/*插入剩余段*/
free(*Lb);
/*释放Lb的头结点*/
Lb=NULL;
voidmain()
intn=5;
LinkListLa,Lb,Lc;
按非递减顺序(正位序建立单链表括"
CreateList2(&
La,n);
/*正位序输入n个元素的值*/
La="
/*输出链表的内容*/
ListTraverse(La,print);
按非递增顺序(逆位序建立单链表"
CreateList(&
Lb,n);
/*逆位序输入n个元素的值*/
Lb="
/*输出链表的内容*/
ListTraverse(Lb,print);
MergeList(La,&
Lb,&
Lc);
/*按非递减顺序归并La和Lb,得到新表Lc*/
Lc="
/*输出链表括Lc的容*/
La和Lb非递减顺序为Lc:
ListTraverse(Lc,print);
Lc单链表的长度为:
"
%d\n"
ListLength(Lc));
在Lc单链表的第i个位置前插入元素e:
\n请输入元素e="
inte;
scanf("
e);
请输入位置i="
i);
ListInsert(Lc,i,e);
将Lc置为空表\n"
ClearList(Lc);
(3)实验过程发现的问题
①.在voidCreateList2(LinkList*L,intn)函数中Scanf("
输入方式不安全
②.在voidCreateList(LinkList*L,intn)函数中Scanf_s("
输入方式不安全
③.在intLocateElem(LinkListL,ElemTypee,Status(*compare)(ElemType,ElemType))函数中
i=0;
LinkListp=L->
逻辑错误
(4)问题分析及解决方案
①.在voidCreateList2(LinkList*L,intn)函数中改为
Scanf_s("
②.在voidCreateList(LinkList*L,intn)函数中改为
将i=0;
改为i=1;
或将LinkListp=L->
改为LinkListp=L->
p指向第一节点。
四.实验结果分析
除了scanf();
函数出错外,intLocateElem(LinkListL,ElemTypee,Status(*compare)(ElemType,ElemType))函数中有逻辑错误,其他函数测试正常。
五.作业小结
(1)StatusListInsert(LinkListL,inti,ElemTypee)中
①.插入新数据只该元素的地址
②.转移原指针
③.拼接新指针
(2)在StatusGetElem(LinkListL,inti,Elemtype*e)中
P=L->
j=1;
while();
查找元素时,如果第i个元素不存在,则返回ERROR
(3)在voidCreateList(LinkList*L,intn)中
P->
next=L->
L->
①转移指针。
②连接指针。
(4)在MergeList(LinkListLa,LinkList*Lb,LinkList*Lc)中
La,Lb为非空表时,pa和pb分别指向表中的第一个结点。
第一个循环条件是Pa,pb都不为空。
六.对原方案的改进意见
intLocateElem(LinkListL,ElemTypee,Status(*compare)(ElemType,ElemType)){若这样的数据元素不存在,则返回值为0*/
或者i=0;
七.实验收获
(1)通过此实验我对单链表进行初始化,建立带头节点的单链表,将单链表按其值非递归排序等操作有了进一步的了解。
(2)再进行插入,删除等操作时,单链表由于顺序表。
(3)对验证实验有了进一步的了解。