数据结构读书报告.docx
《数据结构读书报告.docx》由会员分享,可在线阅读,更多相关《数据结构读书报告.docx(8页珍藏版)》请在冰豆网上搜索。
![数据结构读书报告.docx](https://file1.bdocx.com/fileroot1/2022-12/28/33a0ca2b-75e6-48db-8ca2-37bc62e7c727/33a0ca2b-75e6-48db-8ca2-37bc62e7c7271.gif)
数据结构读书报告
一、需求分析
1.问题描述:
设有n个人围坐在一个圆桌周围,现从第s个人开始报数,数到第m的人出列,然后从出列的下一个人重新开始报数,数到第m的人又出列,…,如此反复直到所有的人全部出列为止。
二、程序分析
2.1存储结构
存储结构:
循环链表
2.2关键算法分析
【设计思想】
首先,设计实现约瑟夫环问题的存储结构。
由于约瑟夫环本身具有循环性质,考虑采用循环链表,为了统一对表中任意节点的操作,循环链表不带头结点。
循环链表的结点定义为如下结构类型:
structNode
{
intnumber;
Node*next;
};
其次,建立一个不带头结点的循环链表并由头指针first指示。
最后,设计约瑟夫环问题的算法。
【伪代码】
1、工作指针first,r,s,p,q初始化
2、输入人数(n)和报数(m)
3、循环n次,用尾插法创建链表
Node*q;
for(inti=1;i<=n;i++)
{
Node*p;
p=newNode;
p->number=i;
p->next=NULL;
if(i==1)L=q=p;
else
{
q->next=p;
q=q->next;
}
}
q->next=L;
if(L!
=NULL){return(L);}
4、输入报数的起始人号数k;
5、Node*q=newNode;计数器初始化i=1;
6、循环n次删除结点并报出位置(其中第一个人后移k个)
当i移动指针m-2次p=p->next;
删除p结点的后一结点q
q=p->next;
p->next=q->next;
*L=p->next;
报出位置后Deleteq;
计数器i++;
【复杂度】
for(inti=1;i<=n;i++)
{
Node*p;
p=newNode;
p->number=i;
p->next=NULL;
if(i==1)L=q=p;
else
{
q->next=p;
q=q->next;
}
时间复杂度:
O(n)
if(i==1)i+=LengthList(*L);
Node*p;
p=*L;
intj=0;
while(jnext;j++;}
q=p->next;
p->next=p->next->next;
*L=p->next;
return(q);
时间复杂度:
O(n2)
算法的空间复杂度:
O(n2)
三、详细设计
#include
usingnamespacestd;
structNode//循环节点的定义
{
intnumber;//编号
Node*next;
};
Node*CreateList(Node*L,int&n,int&m);
//建立约瑟夫环函数
voidJoseph(Node*L,intn,intm);
//输出每次出列号数函数
Node*DeleteList(Node**L,inti,Node*q);
//寻找每次出列人的号数
intLengthList(Node*L);
//计算环上所有人数函数
voidmain()//主函数
{
Node*L;
L=NULL;
//初始化尾指针
intn,m;
cout<<"请输入人数N:
";
cin>>n;//环的长度
if(n<1){cout<<"请输入正整数!
";}//人数异常处理
else
{
cout<<"请输入所报数M:
";
cin>>m;
if(m<1){cout<<"请输入正整数!
";}//号数异常处理
else
{
L=CreateList(L,n,m);//重新给尾指针赋值
Joseph(L,n,m);
}
}
system("pause");
}
Node*CreateList(Node*L,int&n,int&m)//建立一个约瑟夫环(尾插法)
{
Node*q;
for(inti=1;i<=n;i++)
{
Node*p;
p=newNode;
p->number=i;
p->next=NULL;
if(i==1)L=q=p;//工作指针的初始化
else
{
q->next=p;
q=q->next;
}
}
q->next=L;
if(L!
=NULL){return(L);}//返回尾指针
elsecout<<"尾指针异常!
"<}
voidJoseph(Node*L,intn,intm)//输出每次出列的人
{
intk;
cout<<"请输入第一个报数人:
";
cin>>k;
if(k<1||k>n){cout<<"请输入1-"<else
{
cout<<"\n出列顺序:
\n";
for(inti=1;i{
Node*q=newNode;
if(i==1)q=DeleteList(&L,k+m-1,q);//第一个出列人的号数
elseq=DeleteList(&L,m,q);
cout<<"号数:
"<number<deleteq;//释放出列人的存储空间
}
cout<<"最后一个出列号数是:
"<number<}
}
Node*DeleteList(Node**L,inti,Node*q)
//寻找每次出列的人
{
if(i==1)i+=LengthList(*L);
//顺序依次出列情况的处理方式
Node*p;
p=*L;
intj=0;
while(jnext;j++;}
q=p->next;
p->next=p->next->next;
*L=p->next;
return(q);
}
intLengthList(Node*L)
//计算环上的人数
{
if(L){cout<<"尾指针错误!
"<else
{
inti=1;
Node*p=L->next;
while(p!
=L)
{
i++;
p=p->next;
}
return(i);
}
}
四、调试结果
2.测试条件:
如上图所示,人数为20人,所报数为6,第一个报数的人是1号。
3.测试结论:
得出最后出列的人是20号,与算得的结果一致,证明程序正常运行,能够解决一般的约瑟夫环问题。
4.总结
1.调试时出现的问题及解决办法:
利用带头结点的尾插法建立链表求解的时候,头节点的作用无法确定,导致编译通过,但是运行之后的结果都不是正确的运行结果。
苦苦思索,包括和同学讨论,一直没能解决,最后决定改用另一种存储方法,将头节点直接改成NULL,最终测试的结果是正确的。
(但是还未能完全理解原因是什么)
用函数返回存储节点的地址的时候,函数中的一句没有问题的语句出现访问错误,更改函数从而解决了问题。
2.心得体会:
这次做数据结构作业,真是令我大伤脑筋啦,在书上网上看了好多的相关的东西才小有启发,当然也想过很多别的问题,最后觉得约瑟夫环问题是一个比较容易弄出来,但又在一定程度上检验学习成果的问题,在编写程序的过程中最令人头痛的是不断弹出来的error,让人很头疼,同时在完成作业的过程中也明白了其实看别人的程序和自己编写程序根本就是两码事,编写程序需要有自己的构思,想法,就是用自己的脚走出来的,
同时我也感觉到在做事的时候向别人虚心咨询问题的重要性,总之,这个作业完成的有点艰难,甚至有一些不足之处但终究也让我受益匪浅。
3.下一步的改进:
希望下一次自己可以,在做作业的时候可以完成一些更复杂的问题,而且在这个过程中可以更多的有自己的想法而不是网上或是别的地方的东西,在遇到真正的难题的时候再去请教别人。