线性表实验.docx
《线性表实验.docx》由会员分享,可在线阅读,更多相关《线性表实验.docx(20页珍藏版)》请在冰豆网上搜索。
![线性表实验.docx](https://file1.bdocx.com/fileroot1/2023-1/21/389452ea-9501-453a-95e2-f3666cab6859/389452ea-9501-453a-95e2-f3666cab68591.gif)
线性表实验
福州大学数计学院
《数据结构》上机实验报告
专业:
信息与计算科学
学号
031201206
姓名
詹小青
班级
02班
实验名称
实验一:
线性表结构及其应用
实验主要内容
约瑟夫环问题
实
验
目
的
和
要
求
背景知识:
线性表在两种存储结构上的插入、删除及应用。
目的要求:
1.掌握线性表两种存储结构的特点及结构实现方法。
2.掌握线性表两种存储结构基本操作算法的程序实现并能运用。
3、将两个递增有序链表归并为一个递增有序链表
问
题
描
述
和
主
要
步
骤
一、线性表的顺序存储结构
目的要求:
1.掌握顺序存储结构的特点。
2.掌握顺序存储结构的常见算法。
实验内容
1.建立含n个数据元素的顺序表并输出该表各元素的值。
元素的个数及n个元素的值由键盘输入,元素类型为整型。
2.输入整型元素序列,利用有序表插入算法建立一个有序表。
3.输入整型元素序列,利用有序表的删除算法删除表中第i个元素。
二、线性表的链式存储结构
(一)----单链表的有关操作
目的要求:
1.掌握单链表的存储特点及其实现。
2.掌握单链表的插入、删除算法及其应用算法的程序实现。
实验内容
1.随机产生或键盘输入一组元素,建立一个带头结点的单链表(无序)。
2.遍历单链表(即输出单链表中各结点元素)。
3.把单链表中元素逆置。
4.在单向链表中删除所有的偶数元素结点。
5.编写在非递减有序链表中插入一个元素使链表元素仍有序的函数,并利用该函数建立一个非递减有序单链表。
6.利用算法5建立两个非递减有序单链表,然后合并成一个非递减有序单链表。
三、约瑟夫环问题
目的要求:
约瑟夫问题:
编号为1,2,..n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。
试设计一个程序来求出出列顺序,并输出结果。
利用单向循环链表存储结构模拟此过程,按照出列的顺序输出各人的编号。
实
验
结
果
(
截
图
表
示
)
一、线性表的顺序存储结构
程序:
/*Note:
YourchoiceisCIDE*/
#include"stdio.h"
#include"stdlib.h"
#defineok1
#defineerror0
typedefstruct{
int*elem;
intlength;
}sqlist;
intinitlist(sqlist&p)
{
p.elem=(int*)malloc(sizeof(int));
if(!
p.elem)printf("overflow!
");
p.length=0;
returnok;
}
intcreatelist(sqlist&p)
{
inti;
printf("pleaseinputdata:
\n");
for(i=1;i<=p.length;i++)
scanf("%d",&p.elem[i]);
returnok;
}
intinsertlist(sqlist&p,inti,inte){
intj;
if(i<1||i>p.length+1)printf("ierror");
for(j=p.length;j>=i;j--)
p.elem[j+1]=p.elem[j];
p.elem[i]=e;
p.length=p.length+1;
returnok;
}
intdeletelist(sqlist&p,inti){
intj,e;
if(i<1||i>p.length)printf("ierror");
e=p.elem[i];
for(j=i;j<=p.length;j++)
p.elem[j]=p.elem[j+1];
p.length=p.length-1;
returnok;
}
intoutput(sqlist&l){
inti;
printf("outputsqlistdata:
\n");
for(i=1;i<=l.length;i++)
printf("%3d",l.elem[i]);
printf("\n");
returnok;
}
voidmain()
{
sqlistl;
inti,n,e;
initlist(l);
printf("pleasesqlistlength:
\n");
scanf("%d",&n);
l.length=n;
createlist(l);
//output(l);
printf("outputsqlistdata:
\n");
for(i=1;i<=l.length;i++)
printf("%3d",l.elem[i]);
printf("\n");
printf("pleaseinputinsertiande:
\n");
scanf("%d%d",&i,&e);
insertlist(l,i,e);
output(l);
printf("pleaseinputdeletei:
\n");
scanf("%d",&i);
deletelist(l,i);
output(l);
}
实验结果:
二、线性表的链式存储结构
(一)----单链表的有关操作
程序:
#include
#include
usingnamespacestd;
#defineOK1
#defineERROR0
typedefintStatus;
typedefintElemType;
//-------------单链表的存储结构-------------------
typedefstructLNode
{
ElemTypedata;//结点的数据域
structLNode*next;//结点的指针域
}LNode,*LinkList;
//-------------单链表的初始化--------------------
StatusInitList_L(LinkList&L)
{
//构造一个空的链表L
L=newLNode;//生成新结点作为头结点,用头指针L指向头结点
L->next=NULL;//头结点的指针域置空
returnOK;
}
//-------------按序号查找-------------------------
StatusGetElem_L(LinkListL,inti,ElemType&e)
{
//在带头结点的单链表L中查找第i个元素
LinkListp;
p=L->next;//初始化,p指向第一个结点
intj=1;//j为计数器
while(p&&j
{
p=p->next;
++j;
}
if(!
p||j>i)//第i个元素不存在
returnERROR;
e=p->data;//取第i个元素
returnOK;
}
//------------按值查找----------------------------LNode*LocateElem_L(LinkListL,ElemTypee)
{
//在带头结点的单链表L中查找值为e的元素
LNode*p;
p=L->next;
while(p&&p->data!
=e)//寻找满足条件的结点
p=p->next;
returnp;//返回L中值为e的元素的位置;查找失败的话返回NULL
}
//------------插入--------------------------------
StatusListInsert_L(LinkList&L,inti,ElemType&e)
{
LinkListp=L;
intj=0;
while(p&&j{
p=p->next;
++j;
}
if(!
p||j>i-1)
returnERROR;
LinkLists;
s=newLNode;//生成新结点s
s->data=e;//将结点s的数据域置为e
s->next=p->next;//将结点s插入L中
p->next=s;
cout<<"插入完成"<returnOK;
}
//--------------单链表删除------------
StatusListDelete_L(LinkList&L,inti,ElemTypee)
{
LinkListp=L;
LinkListq;
intj=0;
while(p&&j{
p=p->next;
++j;
}
if(!
(p->next)||j>i-1)
returnERROR;//i大于表长+1或小于1
q=p->next;//临时保存被删结点的地址以备释放
p->next=q->next;//改变删除结点前驱结点的指针域
e=q->data;
deleteq;//释放删除结点的数据域
cout<returnOK;
}
//---------------前插法创建链表--逆序输入--------
voidCreateList_F(LinkList&L,intn)
{
L=newLNode;
LinkListp;
L->next=NULL;//先建立一个带头结点的空链表
for(inti=n;i>0;--i)
{
p=newLNode;//生成新结点
cin>>p->data;//输入元素值
p->next=L->next;
L->next=p;//插入到表头
}
}
//--------------后插法创建链表--正序输入----------
voidCreateList_L(LinkList&L,intn)
{
L=newLNode;
LinkListp;
L->next=NULL;
LinkListr=L;//尾指针r指向头结点
for(inti=0;i{
p=newLNode;//生成新结点
cin>>p->data;
p->next=NULL;
r->next=p;
r=p;//r指向新的结点
}
}
intmain()
{
intchoice;
intn;
inti;
ElemTypee;
LNode*L;
cout<<"选项:
"<<<<<<<<"请选择:
"<cin>>choice;
while(i!
=0)
{
switch(choice)
{
case1:
{
intchoice1;
InitList_L(L);
cout<<"1.前插法2.后插法"<<<"请选择:
"<cin>>choice1;
switch(choice1)
{
case1:
cout<<"请输入结点个数:
"<cin>>n;
cout<<"请输入元素值:
"<CreateList_F(L,n);
break;
case2:
cout<<"请输入结点个数:
"<cin>>n;
cout<<"请输入元素值:
"<CreateList_L(L,n);
break;
default:
cout<<"输入有误"<break;
}
break;
}
case2:
{
intchoice1;
cout<<"1.按序号查找2.按值查找"<<<"请选择:
"<cin>>choice1;
switch(choice1)
{
case1:
cout<<"请输入序号";
cin>>i;
GetElem_L(L,i,e);
cout<<"此结点数据域为:
"<break;
case2:
cout<<"请输入值:
";
cin>>e;
cout<<"此数据的第一个位置为:
"<break;
default:
cout<<"输入有误"<break;
}
break;
}
case3:
cout<<"请输入位置:
";
cin>>i;
cout<<"请输入数值:
";
cin>>e;
ListInsert_L(L,i,e);
break;
case4:
cout<<"请输入位置:
";
cin>>i;
ListDelete_L(L,i,e);
break;
case0:
return0;
default:
cout<<"输入有误,请重新输入:
"<}
cout<<"请选择:
";
cin>>choice;
}
return0;
}
/*1105_XL*/
实验结果:
三、约瑟夫环问题
程序:
#include
usingnamespacestd;
#defineTRUE1
#defineFALSE0
#defineOK1
typedefintStatus;
typedefdoubleElemType;
//-----------------------------------
//定义单向循环链表
typedefstructLNode
{
intnumber;
intdata;
structLNode*next;
}LNode,*LinkList;
//-----------------------------------
LinkListEvaluList(intn);//对单向循环链表进行尾插入赋值
intsize(LinkListL);//求链表的节点个数
StatusScanList(LinkListL);//遍历单向循环链表
StatusJoseph(LinkList&L,intm);//约瑟夫环的实现
//------------------------------------------------
voidmain()
{
intm,n;
cout<<"请输入初始密码(正整数)和人数"<cin>>m>>n;
cout<LinkListL=EvaluList(n);
cout<ScanList(L);
cout<Joseph(L,m);
}
//---------对单向循环链表进行尾插入赋值-----------
LinkListEvaluList(intn)
{
if(n==0)
returnNULL;
intkey;
cout<<"输入第1个人的密码";
cin>>key;
LinkListL=newLNode;
L->data=key;
L->number=1;
L->next=L;
for(inti=2;i<=n;i++)
{
LinkListp=newLNode;
intkey;
cout<<"输入第"<
cin>>key;
p->data=key;
p->number=i;
p->next=L->next;
L->next=p;
L=L->next;
}
cout<L=L->next;
returnL;
}
//---------------求链表的节点个数-----------------
intsize(LinkListL)
{
if(L==NULL)
return0;
inti=1;
LinkListp=L->next;
while(p!
=L)
{
i++;
p=p->next;
}
returni;
}
//---------------遍历单向循环链表-----------------
StatusScanList(LinkListL)
{
LinkListp=L;
if(p==NULL)
{
cout<<"人数为空"<returnFALSE;
}
cout<<"第1个人的密码";
cout<data<p=p->next;
while(p!
=L)
{
cout<<"第"<number<<"个人的密码";
cout<data<p=p->next;
}
cout<returnTRUE;
}
//----------------约瑟夫环的实现------------------
StatusJoseph(LinkList&L,intm)
{
if(L==NULL)
{
cout<<"人数为空,出列结束"<returnFALSE;
}
LinkListp=L;
while(p->next!
=L)
p=p->next;
for(intn=size(L);n>0;n--)
{
cout<<"密码为"<for(inti=1;i<=m%n-1;i++)
p=p->next;
cout<next->number<m=p->next->data;
LinkListq=p->next;
p->next=q->next;
free(q);
}
returnOK;
}
实验结果:
研
究
与
探
讨
数据结构像是身体的骨骼,而C++是填充这骨骼的肉体,二者相结合才能使整个程序更加完整,健全。
数据结构是个框架,模型,抽象数据类型中列举了各种操作,而所用的C++语言,将各种操作描述出来构成算法。
数据结构+算法=程序设计。
在这次设计的过程中,我还遇到了很多的问题。
顺序表是按顺序存储的,用了一维数组来存储,又结合C++的程序设计,我又用了类,但是,在执行时出现了问题。
后来我又上网查找资料,重新整理思路,把顺序表的基本操作写好了。
单链表写起来简单多了,但是细节上出了问题。
比如说,有些变量的重复定义,有些变量又没有定义,在调用函数,就直接复制,没有改参数等。
不过好在最后都改过来了。
说明:
实验名称为教学大纲中各章的实验项目名称,实验内容为具体章节的实验内容名称