约瑟夫问题数据结构实验报告汇总.docx
- 文档编号:25201195
- 上传时间:2023-06-06
- 格式:DOCX
- 页数:17
- 大小:117.85KB
约瑟夫问题数据结构实验报告汇总.docx
《约瑟夫问题数据结构实验报告汇总.docx》由会员分享,可在线阅读,更多相关《约瑟夫问题数据结构实验报告汇总.docx(17页珍藏版)》请在冰豆网上搜索。
约瑟夫问题数据结构实验报告汇总
中南民族大学管理学院
学生实验报告
实验项目:
约瑟夫问题
课程名称:
数据结构
年 级:
专 业:
信息管理与信息系统
指导教师:
实验地点:
管理学院综合实验室
完成日期:
小组成员:
2012学年至2013学年度第1学期
一、实验目的
(1)掌握线性表表示和实现;
(2)学会定义抽象数据类型;
(3)学会分析问题,设计适当的解决方案;
二、实验内容
【问题描述】:
编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。
试设计一个程序求出出列顺序。
【基本要求】:
利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。
【测试数据】:
m的初值为20;密码:
3,1,7,2,4,8,4(正确的结果应为6,1,4,7,2,3,5)。
三、实验步骤
(一)需求分析
对于这个程序来说,首先要确定构造链表时所用的插入方法。
当数到m时一个人就出列,也即删除这个节点,同时建立这个节点的前节点与后节点的联系。
由于是循环计数,所以才采用循环列表这个线性表方式。
程序存储结构利用单循环链表存储结构存储约瑟夫数据(即n个人的编码等),模拟约瑟夫的显示过程,按照出列的顺序显示个人的标号。
编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。
试设计一个程序求出出列顺序。
基本要求是利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。
程序执行的命令
(1)构造单向循环链表。
(2)按照出列的顺序引出各个人的标号。
测试数据m的初值为20;密码:
3,1,7,2,4,8,4(正确的结果应为6,1,4,7,2,3,5)
(1)、插入:
在把元素插入到循环链表中时,由于是采用的头插法,所以我保留了front头结点。
在每加入一个节点时,都会直接连接在front后面,从而保证一开始就赋值的rear尾节点不用修改。
伪代码阐释如下:
1)、在堆中建立新节点:
Node
2)、将a[i]写入到新节点的数据域:
s->data=a[i];
3)、修改新节点的指针域:
s->next=front->next;
4)、修改头结点的指针域,将新节点加入到链表中:
front->next=s;
时间复杂度为:
1;
(2)、删除:
首先通过p指针查找到所要删除的节点的前一个节点,继而通过q=p->next简单地删除掉。
假设所要查找的为第i个元素。
伪代码阐释如下:
1)、在堆中建立新节点p,通过循环查找到i-1,将此节点的地址赋给p。
2)、设q指向第i个节点:
若p=rear,则q=front->next;否则,q=p->next;
3)、摘链,即将q从链表中摘除:
若q=rear,则p->next=front->next;否则,则p-next=q->next.
4)、保存q元素的数据:
x=q->data;
5)、释放q元素:
deleteq;
时间复杂度为:
1;
(3)、约瑟夫问题的基本思想:
在这个循环查找问题中,通过循环链表实现了循环查找到节点。
一个关键部分就是删除节点后进行链表的链接,从而保证链表的循环性。
在查找方面上,我利用了一个for循环来计数所查找过的节点。
其中查找的时间复杂度也为1;
(2)概要设计
测试主函数流程:
流程图如下:
否
是
跳出函数
否
是
否
(三)详细设计
#include
usingnamespacestd;
constintd=50000;
structNode
{
intdata;
structNode*next;//声明next指针
};
classClinklist
{
public:
Clinklist(inta[],intn);
voidJosef(intm,intn);
private:
Node*rear;//声明rear和front指针
Node*front;
intn;
};
Clinklist:
:
Clinklist(inta[],intn)
{
rear=newNode;
front=newNode;
front->next=rear;//构造空单链表
rear->next=front;
rear->data=a[n-1];
for(inti=n-2;i>=0;i--)
{
Node*s=newNode;//循环插入元素来建立链表
s->data=a[i];
s->next=front->next;
front->next=s;
}
}
voidClinklist:
:
Josef(intm,intn)
{
Node*p=front;
intj=0;
while(front->next!
=front)
{
inti=0;
while(i!
=m-1)//实现第m-1个节点的查找
{
if(p==rear)
p=front->next;
elsep=p->next;
i++;
}
Node*q=p->next;
if(p==rear)//排除p恰好为rear节点的情况
{q=front->next;
front->next=q->next;
p->next=front->next;
}
else
{
if(q==rear)//排除q恰好为rear节点的情况
p->next=front->next;//完成摘链
else
p->next=q->next;//完成摘链
}
intx=q->data;//保留q点数据
deleteq;//完成q节点的删除
j++;
if(j==n)cout<<"所出的最后一个人的编号是:
"< } } intmain() { intm,n; cout<<"请输入人数(1<=n<=50000): "< cin>>n; intmember[d]; for(inti=0;i { member[i]=i+1; } cout<<"请输入要按那个数进行计算(m>=1): "< cin>>m; if(n<=0||m<=0)throw"所输入的数不符合要求! "; Clinklistpro(member,n);//构造Clinklist类的对象 pro.Josef(m,n); return0; } (四)调试分析 调试时出现的问题及解决的方法 1、早期程序只写了约瑟夫的实现部分,没有对输入的数据进行筛选,测试时会出错。 2、在先前的程序循环过程中没有进行优化,导致循环次数过多,浪费了一定的时间。 3、为了限制在输入过程中不会上溢,只在输入中限定为四个不全为零的数字,但是做的是一个循环。 在约瑟夫的实现在程序中,为for循环,时间复杂度为o(m%n-1)当n=1时,复杂度为o (1)。 4、在调试时一开始用的是模板类,调试时就总会遇到“无法解析的外部指令”之类的问题。 由于无法解决,对模板类的理解不好,所以就去掉了模板类的应用。 Templete 5、“rear指针找不到声明”,这个的解决方案是参照别的线性表例子,加上了如下struct类型的语句,才得以运行正常: structNode { intdata; structNode*next; }; 6、这个是最严重的逻辑错误,就是编译的时候没有任何问题,在程序运行时会出现乱码或者出错的情况。 这个完全靠一点点的逻辑判断了,又用了最笨的方法: 在纸上画一个循环链表才搞定。 (五)用户手册 1、我们这个程序的运行环境为VC++6.0操作系统, 2、进入演示程序后即显示文本方式的用户界面: (六)测试结果 (七)心得体会 数据结构的课程设计,相对来说还是一个较大的工程,我们小组各个成员相互合作,虽然里面的内容不是很完备,但总体上还是一个比较能要体现数据结构的知识点能力的程序了,这个设计让我们在课堂中学到的理论知识,解决相应的实际问题,深入理解和灵活掌握所学的内容,使我们在实践的过程中收获匪浅,认真去做,踏踏实实,静静思考,慢慢进步,会有收获的。 (八)团队介绍 小组成员基本情况介绍组长: 雷灵花11056024 组员: 涂艺11056022 伍雨豪11056029 小组成员分工情况 组长雷灵花,选择的实验设计为第一模块的约瑟夫问题,完成了第一个实验的程序设计和最终实验报告的总结。 组员涂艺,完成了第二个实验的程序设计和实验报告的撰写工作,选择的程序设计为第一模块的城市链表实验。 组员伍宇豪,在进行实验当中查阅了大量的相关资料,给出了实验的程序设计和源代码上的文件资料和指导。 小组成员任务完成情况 程序一和程序二的调试工作完成情况良好,各个结果都能运行,组长实验一的程序和实验报告完成符合老师要求格式,组员涂艺程序和实验报告完成情况基本一致,组员伍宇豪也提供了很多的资料和技术支持。 总体来说,团队意识很好,一起共同完成学习任务。 (九)附录: 源程序清单 源程序文件名清单: #include usingnamespacestd; constintd=50000; structNode { intdata; structNode*next;//声明next指针 }; classClinklist { public: Clinklist(inta[],intn); voidJosef(intm,intn); private: Node*rear;//声明rear和front指针 Node*front; intn; }; Clinklist: : Clinklist(inta[],intn) { rear=newNode; front=newNode; front->next=rear;//构造空单链表 rear->next=front; rear->data=a[n-1]; for(inti=n-2;i>=0;i--) { Node*s=newNode;//循环插入元素来建立链表 s->data=a[i]; s->next=front->next; front->next=s; } } voidClinklist: : Josef(intm,intn) { Node*p=front; intj=0; while(front->next! =front) { inti=0; while(i! =m-1)//实现第m-1个节点的查找 { if(p==rear) p=front->next; elsep=p->next; i++; } Node*q=p->next; if(p==rear)//排除p恰好为rear节点的情况 {q=front->next; front->next=q->next; p->next=front->next; } else { if(q==rear)//排除q恰好为rear节点的情况 p->next=front->next;//完成摘链 else p->next=q->next;//完成摘链 } intx=q->data;//保留q点数据 deleteq;//完成q节点的删除 j++; if(j==n)cout<<"所出的最后一个人的编号是: "< } } intmain() { intm,n; cout<<"请输入人数(1<=n<=50000): "< cin>>n; intmember[d]; for(inti=0;i { member[i]=i+1; } cout<<"请输入要按那个数进行计算(m>=1): "< cin>>m; if(n<=0||m<=0)throw"所输入的数不符合要求! "; Clinklistpro(member,n);//构造Clinklist类的对象 pro.Josef(m,n); return0; } 指导教师批阅: 指标 最高分 评分要素 评分 设计技术水平 30 程序的功能设计、数据结构设计及整体结构设计合理;程序运行情况良好,算法说明清晰,理论分析与计算正确,实验数据无误 实际动手能力 20 熟练使用开发工具,能够迅速准确的进行调试、纠错和运行 编程风格 10 良好的编程风格(缩进,注释,变量名、函数名见名知意等,程序运行界面友好) 报告规范化 10 提交的电子文档及打印文档的书写、存放符合规范化要求 回答问题 20 能简明扼要地阐述设计的主要内容,能准确流利地回答各种问题 学习态度 10 端正的学习态度及认真刻苦程度等 总分 指导教师: 年月日
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 约瑟夫 问题 数据结构 实验 报告 汇总