实验二报告线性表的链式存储.docx
《实验二报告线性表的链式存储.docx》由会员分享,可在线阅读,更多相关《实验二报告线性表的链式存储.docx(14页珍藏版)》请在冰豆网上搜索。
![实验二报告线性表的链式存储.docx](https://file1.bdocx.com/fileroot1/2023-1/31/111f45c8-2bc6-4277-be8c-11ca401e8bdd/111f45c8-2bc6-4277-be8c-11ca401e8bdd1.gif)
实验二报告线性表的链式存储
数据结构实验报告
(实验二)
专业:
______________
班级:
_______________
姓名:
_________________
学号:
___________________
指导老师:
________________
评分:
________________________
实验二线性表的链式存储
一、实验目的
1.掌握线性表的链式存储结构。
2.能熟练地利用链式存储结构实现线性表的基本操作。
3.能熟练地掌握链式存储结构中算法的实现。
二、实验内容
1.分别用头插法和尾插法建立带头结点的单链表。
2.实现单链表上的插入、删除、修改、查找、计数、输出等基本操作。
3.解决约瑟夫问题:
假设有n个人按1、2、3、…、n的顺序围成一圈,现在,从第s个人开始按1、2、3、…、m的顺序报数,数到m的人出圈,接着从出圈的下一个人开始重复此过程,直到所有人出圈为止。
试用循环链表解决这个问题。
三、算法描述
1~2:
程序中先是以一个LNode结构体类型定义结点的式的存储结构定义数据类型,再建立单链表,声明一个变量LNode和一个指针变量*LinkList。
再定义实现单链表基本操作的子函数,包括初始化、求长度、遍历、查找、修改、插入、删除等功能实现的函数,在主函数中调用这些子函数。
3.将n个人按顺序编号排成一列,形成一个单循环链表。
程序以模板形式实现,先定义类CircList,在类外定义相应功能的实现。
getData函数实现对应出列编号的返回,再由Josephus函数调用输出,输出后删除该结点,再重新定义一个新结点作为下一个结点,从新定义的结点开始利用循环找到出圈人位置的结点,输出该结点的信息,再在链表中删除该结点,接着从删除的结点的后面重复此步骤,直到链表中剩下一个结点时停止循环,再把链表中的最后一个结点删除。
按循环时输出的的顺序输出所有出列的编号。
4、程序清单
1~2:
#include
usingnamespacestd;
constintMax=100;
typedefstructLNode//定义存储结构
{
chardata;
structLNode*next;
}LNode,*LinkList;
//建立单链表
intinitlist(LinkList&a)
{
LinkLists;
s=newLNode;
//if(!
s)
//return0;
a=s;
s->next=NULL;
return0;
}
//输入数据
intIndata(LinkList&a)
{
intn;
cin>>n;
if(n<0||n>Max)
{
cout<<"你输入的长度不正确,请重新输入:
";
Indata(a);
}
else
{
cout<<"请输入链表元素:
";
charb;
LinkLists,p;
p=a;
for(inti=1;i<=n;i++)
{
cin>>b;
s=newLNode;
s->data=b;
s->next=NULL;
p->next=s;
p=s;
}
}
return0;
}
//求链表的长度
intlength(LinkLista)
{
LinkListp;
inti;
p=a;
for(i=0;p->next!
=NULL;i++)
p=p->next;
returni;
}
//遍历链表
intPrintList(LinkLista)
{
if(length(a)==0)exit
(1);
LinkListp;
for(p=a->next;p->next!
=NULL;p=p->next)
{
cout<data<<'';
}
cout<data;
return0;
}
//按位查找元素
charGet(LinkLista,inti)
{
LinkListp=a;
intj;
for(j=1;j<=i;j++)
p=p->next;
returnp->data;
}
//修改链表元素
intExchange(LinkLista,inti,chark)
{
LinkListp=a;
intj;
for(j=1;j<=i;j++)
p=p->next;
p->data=k;
return0;
}
//在指定位置插入元素
intInsert(LinkList&a,inti,chark)
{
LinkListp=a;
LinkLists;
intj;
for(j=1;j
p=p->next;
s=newLNode;
s->data=k;
s->next=p->next;
p->next=s;
return0;
}
//删除指定位置的元素
intDelete(LinkList&a,inti)
{
LinkLists,p=a;
intj;
for(j=1;j
p=p->next;
s=p->next;
p->next=p->next->next;
deletes;
return0;
}
voidmain()
{
LinkLists;
voidmenu();
menu();
initlist(s);
charb;
inti;
inth=1;
while(h)
{
intk;
cin>>k;
switch(k)//多分支选择结构
{
case1:
//输入数据
{
cout<<"输入链表长度:
";
Indata(s);
cout<cout<<"链表为:
";
PrintList(s);
menu();
}break;
case2:
//按位查找元素
{
cout<<"请输入要查找元素的位置:
";
cin>>i;
if(i<=0||i>length(s))
{
cout<<"你的输入有误,请重新输入:
";
cin>>i;
}
cout<<"该位置的元素是:
"<menu();
}break;
case3:
//修改链表元素
{
cout<<"请输入要修改元素的位置和改成的元素:
";
cin>>i>>b;
if(i<0||i>length(s))
{
cout<<"你的输入的位置有误,请重新输入位置:
";
cin>>i;
}
Exchange(s,i,b);
cout<<"修改后的链表:
";
PrintList(s);
cout<menu();
}break;
case4:
//在指定位置插入元素
{
cout<<"请输入插入位置和元素:
";
cin>>i>>b;
if(i<0||i>length(s))
{
cout<<"你的输入的位置有误,请重新输入位置:
";
cin>>i;
}
Insert(s,i,b);
cout<<"插入后的链表:
";
PrintList(s);
cout<cout<<"新链表总长度:
";
cout<menu();
}break;
case5:
//删除指定位置的元素
{
cout<<"请输入删除元素的位置:
";
cin>>i;
if(i<0||i>length(s))
{
cout<<"你输入的位置有误,请重新输入:
";
cin>>i;
}
Delete(s,i);
cout<<"删除后的链表:
";
PrintList(s);
cout<cout<<"新链表总长度:
";
cout<menu();
}break;
default:
//结束程序
cout<<"程序结束,请按任意键退出!
"<exit
(1);
}
}
}
//菜单函数
voidmenu()
{
cout<cout<cout<<"-------菜单--------"<cout<<"1.初始化链表"<cout<<"2.按位查找元素"<cout<<"3.修改指定位置元素"<cout<<"4.在指定位置插入元素"<cout<<"5.删除指定位置的元素"<cout<<"6.退出程序"<cout<<"-------------------"<cout<<"请选择:
";
}
输出结果:
1.初始化链表
2.查找元素
3.修改指定位置元素
4.插入元素
5.删除指定位置的元素
6.结束程序
3:
#include
usingnamespacestd;
template
classCircList
{
public:
CircList(Tvalue,intk);//构造函数
CircList(Td=0,CircList*next=NULL):
data(d),link(next){}//结点构造函数
TgetData()const{returncurrent->data;};//返回当前结点值
voidFirster(){current=first;}//设置当前指针为头指针
voidNext(){current=current->link;}//将当前指针指向当前结点的后继
voidInsert(constT&value);//插入新结点
voidDelete();//删除当前结点
voidJosephus(intn,intm);//约瑟夫问题的解决,按顺序输出出列编号
private:
CircList*first,*current,*last;
Tdata;
CircList*link;
};
//循环链表的构造
template
CircList:
:
CircList(Tvalue,intk)
{
first=last=newCircList(value);
first->link=first;
current=NULL;
}
//插入新结点
template
voidCircList:
:
Insert(constT&value)
{
if(current==NULL)
current=first->link=newCircList(value,first);
else{
CircList*newnode=newCircList(value,current->link);
if(current->link=first)last=newnode;
current->link=newnode;
current=current->link;
}
}
//删除当前结点,进入下一个结点
template
voidCircList:
:
Delete()
{
CircList*p=first,*q=last;
while(p->data!
=getData()){q=p;p=p->link;}
current=q->link=p->link;
if(p==first)first=current;
if(p==last)last=q;
}
//约瑟夫问题的解决,按顺序输出出列编号
template
voidCircList:
:
Josephus(intn,intm)
{
Firster();
cout<cout<<"出列的顺序:
";
cout<for(inti=0;i{
for(intj=0;jNext();
if(i!
=n)
{
cout<Delete();
}
}
}
voidmain()
{
CircListclist(1,10000);
intn,m;
cout<<"输入队列总人数:
";
cin>>n;
cout<cout<<"输入出列的数字:
";
cin>>m;
for(inti=2;i<=n;i++)
{
clist.Insert(i);
}
clist.Josephus(n,m);
cout<cout<}
输出结果:
4、心得体会
这两个实验,均是对链表实现的应用,主要是对单链表和单循环链表基本操作的运用,实现时特别要注意的是链表存储结构的结点的使用,通过这两个实验的实践操作,我发现结点的运用是相对较难的部分,使用时需要特别小心。
通过这两个实验,我对链表的运用有了更深一层的认识,但还是感觉底气足,还需更加努力去学习。