实验1链表地操作实验.docx
- 文档编号:25305949
- 上传时间:2023-06-07
- 格式:DOCX
- 页数:15
- 大小:29.98KB
实验1链表地操作实验.docx
《实验1链表地操作实验.docx》由会员分享,可在线阅读,更多相关《实验1链表地操作实验.docx(15页珍藏版)》请在冰豆网上搜索。
实验1链表地操作实验
实验B01:
链表的操作实验
一、实验名称和性质
所属课程
数据结构
实验名称
链表的操作
实验学时
2
实验性质
□验证□综合√设计
必做/选做
√必做□选做
二、实验目的
1.掌握线性表的链式存储结构的表示和实现方法。
2.掌握链表根本操作的算法实现。
三、实验容
1.建立单链表,并在单链表上实现插入、删除和查找操作〔验证性容〕。
2.建立双向链表,并在双向链表上实现插入、删除和查找操作〔设计性容〕。
3.计算一个单链表中数据域值为一个指定值x的结点个数〔应用性设计容〕。
四、实验的软硬件环境要求
硬件环境要求:
PC机〔单机〕
使用的软件名称、版本号以与模块:
Windows环境下的TurboC2.0以上或VC++等。
五、知识准备
前期要求熟练掌握了C语言的编程规如此、方法和单链表和双向链表的根本操作算法。
六、验证性实验
1.实验要求
编程实现如下功能:
〔1〕根据输入的一系列整数,以0标志完毕,用头插法建立单链表,并输出单链表中各元素值,观察输入的容与输出的容是否一致。
〔2〕在单链表的第i个元素之前插入一个值为x的元素,并输出插入后的单链表中各元素值。
〔3〕删除单链表中第i个元素,并输出删除后的单链表中各元素值。
〔4〕在单链表中查找第i个元素,如果查找成功,如此显示该元素的值,否如此显示该元素不存在。
2.实验相关原理:
线性表的链式储结构是用一组任意的存储单元依次存放线性表中的元素,这组存储单元可以是连续的,也可以是不连续的。
为反映出各元素在线性表中的前后逻辑关系,对每个数据元素来说,除了存储其本身数据值之外,还需增加一个或多个指针域,每个指针域的值称为指针,又称作链,它用来指示它在线性表中的前驱或后继的存储地址。
这两个局部的的一起组成一个数据元素的存储映像,称为结点,假如干个结点成链表。
如果一个结点中只含一个指针的链表,如此称单链表。
单链表的存储结构描述如下:
typedefstructLnode{
Elemtypedata;/*数据域*/
structLnode*next;/*指针域*/
}LNODE,*Linklist;/*其中LNODE为结点类型名,Linklist为指向结点的指针类型名*/
【核心算法提示】
1.链表建立操作的根本步骤:
链表是一个动态的结构,它不需要予分配空间,因此建立链表的过程是一个结点“逐个插入〞的过程。
先建立一个只含头结点的空单链表,然后依次生成新结点,再不断地将其插入到链表的头部或尾部,分别称其为“头插法〞和“尾插法〞。
2.链表查找操作的根本步骤:
因链表是一种"顺序存取"的结构,如此要在带头结点的链表中查找到第i个元素,必须从头结点开始沿着后继指针依次"点数",直到点到第i个结点为止,如果查找成功,如此用e返回第i个元素值。
头结点可看成是第0个结点。
3.链表插入操作的根本步骤:
先确定要插入的位置,如果插入位置合法,如此再生成新的结点,最后通过修改链将新结点插入到指定的位置上。
4.链表删除操作的根本步骤:
先确定要删除的结点位置,如果位置合法,如此再通过修改链使被删结点从链表中“卸下〞,最后释放被删结点的空间。
【核心算法描述】
voidcreat1(Linklist&L)/*输入一系列整数,以0标志完毕,将这些整数作为data域并用头插法建立一个带头结点的单链表的函数*/
{L=(Linklist)malloc(sizeof(LNODE));/*生成头结点*/
L->next=NULL;/*头结点的指针域初始为空*/
scanf("%d",&node);
while(node!
=0)
{p=(Linklist)malloc(sizeof(LNODE));/*为一个新结点的分配空间*/
p->data=node;/*为新结点数据域赋值*/
p->next=L->next;/*新结点指针域指向开始结点*/
L->next=p;/*头结点指针域指向新结点,即新结点成为开始结点*/
scanf("%d",&node);
}
}
voidcreat2(Linklist&L)/*输入一系列整数,以0标志完毕,将这些整数作为data域并用尾插法建立一个带头结点的单链表的函数*/
{L=(Linklist)malloc(sizeof(LNODE));/*为头结点分配空间*/
L->next=NULL;/*头结点的指针域初始为空*/
r=L;/*尾指针初始指向头结点*/
scanf("%d",&node);
while(node!
=0)
{p=(Linklist)malloc(sizeof(LNODE));/*为一个新结点分配空间*/
p->data=node;/*新结点数据域赋值*/
p->next=NULL;/*新结点指针域为空*/
r->next=p;/*尾结点指针域指向新结点*/
r=p;/*尾指针指向新结点,即新结点成为尾结点*/
scanf("%d",&node);
}
}
statuslist_search(LinklistL,inti;Elemtype&e)
/*在带头结点的单链表L中查找第i个元素,如果查找成功如此用e返回其值*/
{p=L->next;/*使指针p指向第1个元素结点*/
j=1;/*计数器赋初值为1*/
while(p&&j
{p=p->next;
j++;
}
if(!
p&&j>i)
returnERROR;/*如果i值不合法,即i值小于1或大于表长,如此出错*/
e=p->data;/*如果第i个元素存在,如此将该元素值赋给e*/
returnOK;
}
statuslist_insert(Linklist&L,inti;Elemtypex)
/*在带头结点的单链表L中第i个位置之前插入新元素x*/
{p=L;j=0;
while(p!
=NULL&&j {p=p->next; ++j; } if(p==NULL||j>i-1) returnERROR;/*假如位置不正确,即i小于1或大于表的长度加1,如此出错*/ s=(Linklist)malloc(sizeof(LNODE));/*分配一个新结点的空间*/ s->data=x;/*为新结点数据域赋值*/ /*下面两条语句就是完成修改链,将新结点s插入到p结点之后*/ s->next=p->next;/*新结点指针域指向p的后继结点*/ p->next=s;/*新结点成为p的后继结点*/ returnOK; } statuslist_delete(Linklist&L,inti,Elemtype&x) /*在带头结点的单链表L中,删除第i个元素结点,并用x返回其值*/ {p=L;j=0; while(p->next! =NULL&&j {p=p->next; ++j; } if(p->next==NULL||j>i-1) returnERROR;/*假如位置不正确,即i小于1或大于表长,如此出错*/ q=p->next;/*q指向p的后继结点*/ p->next=q->next;/*q的后继结点成为p的后继结点*/ x=q->data;/*用x返回第i个位置的元素*/ free(q);/*释放q所指的被删结点的空间*/ returnOK; } 3.源程序代码参考 #include #include typedefstructLnode {intdata; structLnode*next; }LNODE,*Linklist; Linklistcreat(LinklistL)/*单链表建立函数*/ {intnode;Linklistp; L=(Linklist)malloc(sizeof(LNODE)); L->next=NULL; printf("\npleaseinputthenode(endwith0): \n"); /*请求输入线性表中各个元素,以0完毕*/ scanf("%d",&node); while(node! =0) {p=(Linklist)malloc(sizeof(LNODE)); if(! p)exit(); p->data=node; p->next=L->next; L->next=p; scanf("%d",&node); } returnL; } Linklistinsert(LinklistL,inti,intx)/*单链表插入函数*/ {intj;Linklistp,s; p=L;j=0; while(p! =NULL&&j {p=p->next; ++j; } if(p==NULL||j>i-1) printf("\nERRORposition! \n"); else {s=(Linklist)malloc(sizeof(LNODE)); s->data=x; s->next=p->next; p->next=s; } returnL; } Linklistdelete(LinklistL,inti)/*单链表删除函数*/ {intj,x;Linklistp,q; p=L;j=0; while(p->next! =NULL&&j {p=p->next; ++j; } if(p->next==NULL||j>i-1) printf("\nERROEposition! \n"); else {q=p->next; p->next=q->next; x=q->data; printf("thedeletedatais: %d\n",x); free(q); } returnL; } intsearch(LinklistL,inti)/*单链上的查找函数*/ {Linklistp;intj; p=L->next; j=1; while(p&&j {p=p->next; j++; } if(! p&&j>i) return0;/*如果i值不合法,即i值小于1或大于表长,如此函数返回0值*/ else return(p->data);/*否如此函数返回第i个元素的值*/ } voiddisplay(LinklistL)/*单链表元素输出函数*/ {Linklistp; p=L->next; while(p! =NULL) {printf("%4d",p->data); p=p->next; } printf("\n"); } main()/*主函数*/ {LinklistL=NULL;inti,x; L=creat(L);/*调用单链表建立函数*/ printf("theLinklistis: \n"); display(L);/*调用单链表元素输出(遍历)函数*/ printf("pleaseinputthepositionyouwanttoinsert: ");/*请求输入插入操作位置*/ scanf("%d",&i); printf("pleaseinputthenodeyouwanttoinsert: ");/*请求输入需要插入的元素*/ scanf("%d",&x); L=insert(L,i,x);/*调用单链表插入函数*/ printf("theLinklistafterinsertedis: \n"); display(L);/*调用单链表元素输出(遍历)函数*/ printf("pleaseinputthenodepositionyouwanttodelete: ");/*请求输入删除操作位置*/ scanf("%d",&i); L=delete(L,i);/*调用单链表删除函数*/ printf("theLinklistafterdeletedis: \n"); display(L);/*调用单链表元素输出(遍历)函数*/ printf("pleaseinputthepositionyouwanttosearch: ");/*请求输入待查找元素的位置*/ scanf("%d",&i); x=search(L,i);/*调用单链表查找函数*/ if(x)/*如果查找成功,如此显示第i个元素的值,否如此显示第i个元素不存在*/ printf("the%dthelemis%d\n",i,x); else printf("the%dthelemisnotexsit\n"); } 4.运行结果参考如图2-1所示: 图2-1: 验证性实验运行结果 七、设计性实验 1.编程实现在双向循环链表上的插入、删除和查找操作 1实验要求 〔1〕输入链表的长度和各元素的值,用尾插法建立双向循环链表,并输出链表中各元素值,观察输入的容与输出的容是否一致。 〔2〕在双向循环链表的第i个元素之前插入一个值为x的元素,并输出插入后的链表中各元素值。 〔3〕删除双向循环链表中第i个元素,并输出删除后的链表中各元素值。 〔4〕在双向循环链表中查找值为x元素,如果查找成功,如此显示该元素在链表中的位置,否如此显示该元素不存在。 ⑵核心算法提示 双向循环链表采用的存储结构描述如下: typedefstructDULNODE {Elemtypedata;/*数据域*/ structDULNODE*prior;/*指向前驱结点的指针域*/ structDULNODE*next;/*指向后继结点的指针域*/ }DULNODE,*DuLinklist; typedefintElemtype; 不论是建立双向循环链表还是在双向循环链表中进展插入、删除和查找操作,其操作方法和步骤都跟单链表类似。 只不过要注意两点: 〔1〕但凡在操作中遇到有修改链的地方,都要进展前驱和后继两个指针的修改。 〔2〕单链表操作算法中的判断条件: p==NULL或p! =NULL,在循环链表的操作算法中如此需改为: p! =L,其中L为链表的头指针。 ⑶核心算法描述 voidDuList_creat(DuLinklist&L,intn)/*输入n个整数〔其中n为表长〕,将这些整数作为data域并用尾插法建立一个带头结点的双向循环链表的函数*/ {L=(DuLinklist)malloc(sizeof(DULNODE));/*为头结点分配空间*/ L->next=L->prior=L; /*使头结点的后继指针和前驱指针都指向自身,形成空的双向循环链表*/ r=L;/*尾指针初始指向头结点*/ for(i=0;i {p=(DuLinklist)malloc(sizeof(DULNODE));/*为一个新结点分配空间*/ scanf("%d",&p->data);/*从键盘输入值,并保存在新结点数据域中*/ p->next=r->next;/*新结点后继指针指向尾结点r的后继结点*/ p->prior=r;/*新结点的前驱指针指向尾结点r*/ r->next=p;/*尾结点的后继指针指向新结点*/ r=p;/*尾指针指向新结点,即新结点成为尾结点*/ } L->prior=r;/*使尾结点成为头结点的前驱结点*/ } statusDuList_search(DuLinklistL,inti;Elemtype&e) /*在带头结点的双向循环链表L中查找第i个元素,如果查找成功如此用e返回其值*/ {p=L->next;/*使指针p指向第1个元素结点*/ j=1;/*计数器赋初值为1*/ while(p! =L&&j {p=p->next; j++; } if(j! =i) returnERROR;/*如果i值不合法,即i值小于1或大于表长,如此出错*/ e=p->data;/*如果第i个元素存在,如此将该元素值赋给e*/ returnOK; } statusDuList_insert(DuLinklist&L,inti;Elemtypex) /*在带头结点的双向循环链表L中第i个位置之前插入新元素x*/ {p=L->next;j=1; while(p! =L&&j {p=p->next; ++j; } if(j! =i) returnERROR;/*假如位置不正确,即i小于1或大于表的长度加1,如此出错*/ s=(DuLinklist)malloc(sizeof(DULNODE));/*为一个新结点s分配空间*/ s->data=x;/*为新结点数据域赋值*/ /*下面四条语句就是完成修改链,将新结点s插入到p结点之前*/ s->next=p; p->prior->next=s; s->prior=p->prior; p->prior=s; returnOK; } statusDuList_delete(DuLinklist&L,inti,Elemtype&x) /*在带头结点的双向循环链表L中,删除第i个元素结点,并用x返回其值*/ {p=L->next;j=1; while(p! =L&&j {p=p->next; ++j; } if(j! =i) returnERROR;/*假如位置不正确,即i小于1或大于表长,如此出错*/ q=p;/*记下被删结点*/ p->prior->next=p->next;/*修改链使得p结点从链中脱离*/ p->next->prior=p->prior; x=q->data; printf("thedeletedatais: %d\n",x); free(q);//释放被删结点空间 returnOK; } 提醒: 请将上述算法与单链表上相应操作的算法对照学习,特别注意它们不一样的地方。 八、应用性设计实验 编写一个程序,计算出一个单链表中数据域值为一个指定值x的结点个数。 实验要求: ⑴从键盘输入假如干个整数,以此序列为顺序建立一个不带头结点的单链表; ⑵输出此单链表中的各个数据元素值; 2给定一个x的具体整数值,计算并返回此单链表中数据域值为x的结点个数值。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 操作