实验二 单链表基本操作的实现.docx
《实验二 单链表基本操作的实现.docx》由会员分享,可在线阅读,更多相关《实验二 单链表基本操作的实现.docx(18页珍藏版)》请在冰豆网上搜索。
![实验二 单链表基本操作的实现.docx](https://file1.bdocx.com/fileroot1/2023-2/8/14b0935d-4030-4b1b-8d14-6df375d9e951/14b0935d-4030-4b1b-8d14-6df375d9e9511.gif)
实验二单链表基本操作的实现
实验二单链表基本操作的实现
【实验课程名称】数据结构
【实验项目名称】单链表基本操作的实现
【实验目的】
1理解单链表的存储结构及基本操作的定义;
2掌握单链表存储基本操作;
3学会设计实验数据验证程序。
【实验仪器及环境】计算机,windowxp操作系统,VC++6.0
【实验内容及步骤】
1.单链表顺序存储基本操作
存储结构定义:
typedefstructLNode{//结点类型
ElemTypedata;
structLNode*next;
}*Link,*Position;
typedefstruct{//链表类型
Linkhead,tail;
intlen;
}LinkList;
实现的基本操作:
#include
#include
#include
#include
usingnamespacestd;
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
#defineOVERFLOW-2
typedefintStatus;
typedefintElemType;
typedefstructLNode{//结点类型
ElemTypedata;
structLNode*next;
}*Link,*Position;
typedefstruct{//链表类型
Linkhead,tail;
intlen;
}LinkList;
PositionMakeNode_L(Link&p,ElemTypee)//创建结点
{
p=(Link)malloc(sizeof(LNode));
if(!
p)returnERROR;
p->data=e;
p->next=NULL;
returnp;
}
voidFreeNode_L(Link&q)//释放结点
{
free(q);
}
StatusInitList_L(LinkList&L){
//初始化L为一个带头结点的空链表,头尾指针指向头结点,表长赋
ElemTypee;
e=-1;//实际应用中此初始化语句需要修改
if(!
MakeNode_L(L.head,e))returnERROR;//开辟头结点
L.tail=L.head;L.len=0;
returnOK;
}//InitList_L
StatusDestroyList_L(LinkList&L){//销毁链表L
Linkp;
while(p=L.head->next){//依次释放有序链表中第一个元素至最后一个元素所占用空间;
L.head->next=p->next;
free(p);
}
free(L.head);
L.head=NULL;L.tail=NULL;L.len=0;
cout<"<returnOK;
}//DestroyList_L
StatusClearList_L(LinkList&L){//清空线性单链表
Linkp,q;
p=L.head->next;
while(p)
{
q=p->next;
free(p);
p=q;
}
L.tail=L.head;
L.len=0;
returnOK;
}
StatusInsFirst_L(LinkList&L,Links)//在首元素前插入一个结点
{
s->next=L.head->next;
if(!
L.head->next)
L.tail=s;
L.head->next=s;
L.len++;
returnOK;
}
StatusDelFirst_L(LinkList&L,Linkh,Link&q)//删除首结点
{
h=L.head;
q=L.head->next;
if(q)
{
h->next=q->next;
q->next=NULL;
if(!
h->next)
L.tail=h;
L.len--;
returnOK;
}
else
returnERROR;
}
StatusAppend_L(LinkList&L,Links)//将两个链表跟一个字符串连接起来
{
Linkq;
if(!
L.head->next)
L.head->next=q=s;
else
L.tail->next=q=s;
while(q->next)
{
q=q->next;
}
L.tail=q;
returnOK;
}
PositionRemove_L(LinkList&L,Link&q)//删除尾结点
{
Linkp;
p=L.head;
if(!
L.head->next)cout<<"TheLinkListisempty!
"<else
{
while(p->next!
=L.tail)
p=p->next;
q=L.tail;
L.tail=p;
L.tail->next=NULL;
L.len--;
}
returnq;
}
StatusInsBefore_L(LinkList&L,Link&p,Links)//在p指向的结点前插入一个结点
{
Linkq;
q=L.head;
if(p==L.head)cout<<"不能在这个地方插入元素!
"<else
{
while(q->next!
=p)
q=q->next;
s->next=p;
q->next=s;
}
L.len++;
returnOK;
}
StatusInsAfter_L(LinkList&L,Link&p,Links)//在p指向的结点后插入一个结点
{
if(p==L.tail)L.tail=s;
s->next=p->next;
p->next=s;
L.len++;
returnOK;
}
StatusSetCurElem_L(Link&p,ElemTypee)//改变p指向的结点的内容
{
p->data=e;
returnOK;
}
ElemTypeGetCurElem_L(Linkp)//获取p指向的结点的内容
{
returnp->data;
}
intListLength_L(LinkListL)//获取单链表的长度值
{
returnL.len;
}
StatusListEmpty_L(LinkListL)//判断单链表是否为空,是返回,否返回
{
if(L.head==L.tail)returnTRUE;
elsereturnFALSE;
}
PositionGetHead_L(LinkListL)//获取头指针的地址
{
returnL.head;
}
PositionGetLast_L(LinkListL)//获取尾指针的地址
{
returnL.tail;
}
PositionPriorPos_L(LinkListL,Linkp)//获取p的前驱
{
Linkq;
q=L.head;
if(p==L.head->next)returnNULL;
else
while(q->next!
=p)
q=q->next;
returnq;
}
PositionNextPos_L(LinkListL,Linkp)//获取p的后继
{
if(!
p->next)returnNULL;
returnp->next;
}
StatusLocatePos_L(LinkListL,inti,Link&p)//查找p在单链表中的位置i
{
intj;
if(i<1)returnERROR;
p=L.head->next;
for(j=1;j
p=p->next;
if(!
p)returnERROR;
returnOK;
}
Statuscompare(ElemTypex,ElemTypey)//比较函数
{
if(x==y)
return1;
else
return0;
}
StatusLocateElem_L(LinkListL,ElemTypee,Link&p)//返回跟e相同的值,没有的话返回空指针
{
inti=0;
p=L.head;
do
{
i++;
p=p->next;
}while(p&&!
compare(p->data,e));
if(p)
cout<
else
cout<<"Itisnotinhere!
"<returnOK;
}
StatusListTraverse_L(LinkListL,Status(*visit(ElemType)))//每一个元素调用visit()函数
{
Linkp;
p=L.head->next;
while(p->next)
{
visit(p->data);
p=p->next;
}
returnOK;
}
StatusListInsert_L(LinkList&L,inti,ElemTypee)//在第i个位置后插入一个元素
{
intj;
Linkp,s;
s=(Link)malloc(sizeof(LNode));
p=L.head->next;
for(j=1;j
p=p->next;
s->data=e;
s->next=p->next;
p->next=s;
L.len++;
returnOK;
}
StatusListDelete_L(LinkList&L,inti)//删除第i个元素的结点
{
if(i>L.len)returnERROR;
intj;
Linkp;
p=L.head->next;
for(j=1;jp=p->next;
p->next=p->next->next;
L.len--;
returnOK;
}
StatusMergeList_L(LinkListLa,LinkListLb,LinkList&Lc)//将两个字符串连接起来
{
Linkp,q,t;
p=La.head->next;
q=Lb.head->next;
while(p&&q){
if(p->datadata){
MakeNode_L(t,p->data);
InsFirst_L(Lc,t);
p=p->next;
}
else{
MakeNode_L(t,q->data);
InsFirst_L(Lc,t);
q=q->next;
}
}
while(p){
MakeNode_L(t,p->data);
InsFirst_L(Lc,t);
p=p->next;
}
while(q){
MakeNode_L(t,q->data);
InsFirst_L(Lc,t);
q=q->next;
}
returnOK;
}
【测试数据及实验结果】
intmain(){
LinkListla,lb,lc;
Linkp,q,s,k,t;
InitList_L(la);
InitList_L(lb);
InitList_L(lc);
cout<<"建立一个有个数据的顺序表La,各节点值依次为:
4,6,8,10,12,….,38,40"<cout<<"-----------------------------------"<for(inti=20;i>=1;i--){
MakeNode_L(p,2*i);
InsFirst_L(la,p);
}
q=la.head->next;
while(q){
cout<data;
q=q->next;
}
cout<cout<cout<<"----------------------------------"<ListDelete_L(la,8);
ListDelete_L(la,30);
q=la.head->next;
while(q){
cout<data;
q=q->next;
}
cout<cout<<"-----------------------------------"<cout<<"表长为:
"<cout<<"-----------------------------------"<cout<<"在第五个结点后插入一个结点"<cout<<"-----------------------------------"<ListInsert_L(la,5,11);
q=la.head->next;
while(q){
cout<data;
q=q->next;
}
cout<cout<<"-----------------------------------"<cout<<"分别查找值为,45的元素"<cout<<"-----------------------------------"<LocateElem_L(la,28,s);
LocateElem_L(la,45,s);
cout<<"-----------------------------------"<cout<<"建立线性表Lb,各结点值依次为:
"<cout<<"3,8,13,18,23,28,33,38,43,48,53,58,63,68,73,78"<cout<<"-----------------------------------"<for(inti=7;i>=0;i--){
MakeNode_L(p,i*10+8);
InsFirst_L(lb,p);
MakeNode_L(p,i*10+3);
InsFirst_L(lb,p);
}
q=lb.head->next;
while(q){
cout<data;
q=q->next;
}
cout<cout<<"-----------------------------------"<cout<<"将La和Lb合并为线性表Lc"<cout<<"-----------------------------------"<MergeList_L(la,lb,lc);
q=la.head->next;
cout<<"-----------------------------------"<cout<<"输出La,Lb,Lc的以及各表的表长"<cout<<"-----------------------------------"<while(q){
cout<data;
q=q->next;
}
cout<q=lb.head->next;
while(q){
cout<data;
q=q->next;
}cout<while(q){
cout<data;
q=PriorPos_L(lc,q);
}
cout<cout<<"-----------------------------------"<cout<<"清空线性表La,Lb;输出La,Lb的表长"<cout<<"-----------------------------------"<cout<ClearList_L(la);
cout<ClearList_L(lb);
cout<return0;
}
【实验小结】
举例说明求解什么样的问题用顺序存储,什么样的问题用链式存储较好?
答:
使用顺序存储结构的情况:
(1)空间利用率较高;
(2)存取某个元素速度快;(3)插入元素和删除元素存在元素移动,速度慢,耗时;(4)有空间限制,当需要存取的元素个数可能多于顺序表的元素个数时,会出现"溢出"问题.当元素个数远少于预先分配的空间时,空间浪费巨大。
在存取元素频繁,但删除或插入操作较少的情况宜用顺序表。
例如建立一个班学生的资料,一般学生人数变动较少,而对资料的调用较多,股宜用顺序表。
使用链式存储结构的情况:
(1)占用额外的空间以存储指针(浪费空间);
(2)存取某个元素速度慢;(3)插入元素和删除元素速度快;(4)没有空间限制,存储元素的个数无上限,基本只与内存空间大小有关。
【源代码说明】
1.文件名:
.cpp
2.操作说明:
只需使用visualc++6.0软件将其打开,点击运行即可!