敢死队问题说明书.docx
《敢死队问题说明书.docx》由会员分享,可在线阅读,更多相关《敢死队问题说明书.docx(28页珍藏版)》请在冰豆网上搜索。
![敢死队问题说明书.docx](https://file1.bdocx.com/fileroot1/2022-11/23/1e52130b-0c3f-4572-a032-cb8da23b31c0/1e52130b-0c3f-4572-a032-cb8da23b31c01.gif)
敢死队问题说明书
*******************
实践教学
*******************
兰州理工大学
计算机与通信学院
2012年春季学期
算法与数据结构课程设计
题目:
敢死队问题
专业班级:
软件工程基地
姓名:
学号:
10240539
指导教师:
王旭阳
成绩:
_______________
目录
摘要1
1.采用类c语言定义相关的数据类型2
2.各模块的伪码算法3
3.函数的调用关系图6
4.调试分析7
5.测试结果8
6.源程序(带注释)8
总结17
参考文献18
致谢19
附件Ⅰ任务一源程序代码20
摘要
敢死队问题是根据著名的“约瑟夫环”演变而来的敢死队问题的处理与计算来设计的一个系统。
整个系统从符合操作简便、界面友好、灵活、实用、安全的要求出发,完成敢死队问题的全过程,包括创建四个数据结构(顺序存储结构、单链表存储结构、循环队列存储结构、数组存储结构)、数据的处理与计算、数据的分析、结果的输出。
关键字:
敢死队问题顺序表单向循环链表循环队列数组
1.采用类c语言定义相关的数据类型
//单向循环链表结点定义
typedefstructlnode
{
intnum;//战士编号
structlnode*next;//指向下个结点的指针
}lnode;
//顺序表定义
typedefstructNList
{
intlength;
intmark[10];
}NList;
//循环队列定义
typedefstructCirQueue
{
intdata[QueueSize];
intfront;//代表数组存放的第一个数据对应的下标,即对头
intrear;//代表数组存放的最后一个数据对应的下标,对尾
intcount;//计数器,记录队中元素总数
}CirQueue;
//函数声明
/////////////////////////////////////////////////开始菜单,版权声明
voiddisplay1();////含有声明
voiddisplay2();////选择菜单
voidclearline();////清除多余的输入
/////////////////////////////////////////////////////循环队列函数声明
voidInitial(CirQueue*Q);//初始化队列函数
intIsEmpty(CirQueue*Q);//判断队是否为空
intIsFull(CirQueue*Q);//判断队列是否为空
voidEnQueue(CirQueue*Q,intx);//入队操作
intDeQueue(CirQueue*Q);//删除操作
voidCirqueue(intnum,intCCC);//队列方法处理数据
/////////////////////////////////////////////////////////////////////////
voidOne_way(intM,intCCC);///////////////////////////单向循环链表算法
/////////////////////////////////////////////////////////////////////////
voidArray(intpeople,intCCC);///////////////////////////////////数组算法
/////////////////////////////////////////////////////////////////////////
voidNlist(intnum,intCCC);//////////////////////////////////////顺序表算法
2.各模块的伪码算法
(一)主函数
voidmain()
{
display1();
intchoice;//菜单选择
intnum;//战士数目
while(cin>>choice)
{
if(choice<1||choice>4)
{
cout<<"请选择正确的菜单:
";
continue;
}
if(choice==1||choice==3||choice==4)
cout<<"请输入不超过"<";
else
cout<<"请输入战士数目(数字):
";
///////输入战士数目
while(!
(cin>>num))
{
cin.clear();
while(cin.get()!
='\n')
continue;
cout<<"请正确输入:
";
}
clearline();
while(num<2)
{
if(num<1)////////对输入的数目小于1,作出反应
{cout<<"战士数目不能少于一人!
\n请重新输入:
";
cin>>num;
continue;
}
elseif(num==1)////////对输入战士数目为1的情况,作出反应
{
cout<<"只有一个战士,别无选择!
\n请重新输入:
";
cin>>num;
continue;
};
}
switch(choice)///////////当输入大于1人时,根据选择的数据类型,进行处理
{
case1:
Nlist(num);break;
case2:
One_way(num);break;
case3:
Cirqueue(num);break;
case4:
Array(num);break;
}
display2();/////再次输出选择菜单
}
}
(二)循环队列方法
voidCirqueue(intnum,intCCC)
{
inti,start,count,j;
CirQueues;
for(start=1;start<=num;start++)//start为测试起点
{
Initial(&s);//初始化队列
for(i=1;i<=num;i++)//将所有士兵的编号依次进队
{
EnQueue(&s,i);
};
for(i=1;i{j=DeQueue(&s);//删除队头结点
EnQueue(&s,j);//这两句是把队头的元素取出来然后放到队尾去,经过这个循环以后,要从那个开始的士兵的编号就会在队的队头位置了
};
count=0;//删除结点数
while(count{
for(i=1;i{
j=DeQueue(&s);
EnQueue(&s,j);//这两句是把队头的元素取出来然后放到对尾
};//经过这个循环以后,队头的那个节点的值就是数到5对应的节点
j=DeQueue(&s);//把这个节点出队,但是没有在把它放到队尾,就相当于把它删除了
count++;
};//同第一个方法是一样,删除点数为m-1是结束循环
if(s.data[s.front]==1)break;//此时队只剩一个点,如果是排长就输出
}
cout<<"应从第:
"<}
3.函数的调用关系图
4.调试分析
a、调试中遇到的问题及对问题的解决方法
说明:
(1)本程序运行的环境是VisualC++2010;
(2)程序运行后,显示的提示信息为选择使用数据类型的菜单,正确输入后,会依次出现提示输入战士数目,报数数字。
均正确输入后,即可输出相应的计算结果。
(3)调试
调试过程中,出现如下错误信息:
发现错误为:
“usingnamespacestd”指令只声明在main()内部。
改正为:
将“usingnamespacestd”指令声明为全局范围,即可正确运行。
b、算法的时间复杂度和空间复杂度
时间复杂度为:
T(n)=O(mn);
空间复杂度为:
S(n)=O(f(n));
5.测试结果
6.源程序(带注释)
#include
usingnamespacestd;
constintQueueSize=10;
//单向循环链表结点定义
typedefstructlnode
{
intnum;//战士编号
structlnode*next;//指向下个结点的指针
}lnode;
//顺序表定义
typedefstructNList
{
intlength;
intmark[10];
}NList;
//循环队列定义
typedefstructCirQueue
{
intdata[QueueSize];
intfront;//代表数组存放的第一个数据对应的下标,即对头
intrear;//代表数组存放的最后一个数据对应的下标,对尾
intcount;//计数器,记录队中元素总数
}CirQueue;
//函数声明
/////////////////////////////////////////////////开始菜单,版权声明
voiddisplay1();////含有声明
voiddisplay2();////选择菜单
voidclearline();////清除多余的输入
/////////////////////////////////////////////////////循环队列函数声明
voidInitial(CirQueue*Q);//初始化队列函数
intIsEmpty(CirQueue*Q);//判断队是否为空
intIsFull(CirQueue*Q);//判断队列是否为空
voidEnQueue(CirQueue*Q,intx);//入队操作
intDeQueue(CirQueue*Q);//删除操作
voidCirqueue(intnum,intCCC);//队列方法处理数据
/////////////////////////////////////////////////////////////////////////
voidOne_way(intM,intCCC);///////////////////////////单向循环链表算法
/////////////////////////////////////////////////////////////////////////
voidArray(intpeople,intCCC);///////////////////////////////////数组算法
/////////////////////////////////////////////////////////////////////////
voidNlist(intnum,intCCC);//////////////////////////////////////顺序表算法
////////////////////////////////////////////////////////////////////////
intmain()
{
display1();
intchoice;//菜单选择
intnum;//战士数目
intCCCC;///报数数字
while(cin>>choice)////////////////对输入非菜单选项的数字作出反应
{
if(choice<1||choice>4)
{
cout<<"请选择正确的菜单:
";
continue;
}
////////////////////////////输入战士数目
if(choice==1||choice==3||choice==4)/////当选择的数据结构中含有数组时,提示最大值
cout<<"请输入不超过"<";
else
cout<<"请输入战士数目(数字):
";
while(!
(cin>>num))////////对输入进行检测并作出反应
{
cin.clear();
while(cin.get()!
='\n')
continue;
cout<<"请正确输入:
";
}
clearline();//////////对输入如"123abc"的情况作出处理,清除结尾的字符
while(num<2)
{
if(num<1)////////对输入的树木小于1,作出反应
{cout<<"战士数目不能少于一人!
\n请重新输入:
";
cin>>num;
continue;
}
elseif(num==1)////////对输入战士数目为1的情况,作出反应
{
cout<<"只有一个战士,别无选择!
\n请重新输入:
";
cin>>num;
continue;
};
}
cout<<"请输入报数数字:
";
cin>>CCCC;
switch(choice)///////////当输入大于1人时,根据选择的数据类型,进行处理
{
case1:
Nlist(num,CCCC);break;
case2:
One_way(num,CCCC);break;
case3:
Cirqueue(num,CCCC);break;
case4:
Array(num,CCCC);break;
}
display2();////////////输出菜单,进行下一次测试
}
}
///////////////////////////////////////////////开始菜单和版权声明函数定义
voiddisplay1()
{
cout<<"**************************************"<<<"*《敢死队》丁婷*"<<<"*版权所有翻版必究*"<<<"**************************************"<<"\n\n\n\n\n";
cout<<"请选择数据类型:
1、顺序表2、单向循环链表3、循环队列4、数组Q、退出"<}
voiddisplay2()///////////////选择菜单
{
cout<<"\n\n请选择数据类型:
1、顺序表2、单向循环链表3、循环队列4、数组Q、退出"<}
voidclearline()////////清除当前行多余的部分
{
while(cin.get()!
='\n')
continue;
}
/////////////////////////////////////////////////////////////循环队列方法
//初始化对令队为空
voidInitial(CirQueue*Q)
{
Q->front=Q->rear=0;//对头等于对尾代表队列为空
Q->count=0;
}
//判队列是否为空
intIsEmpty(CirQueue*Q)
{
if(Q->count==0)return1;//如果队里的元素个数为0,队列空,返回1
elsereturn0;
}
//判队列是否满
intIsFull(CirQueue*Q)
{
if(Q->count==QueueSize)return1;
elsereturn0;
}
//将元素进队
voidEnQueue(CirQueue*Q,intx)
{
if((Q->rear+1)%QueueSize==Q->front)
{
printf("列满\n");
exit
(1);
};///如果堆满就退出程序
Q->count++;//否则就进入,元素总数加一
Q->data[Q->rear]=x;//数组的最后一位赋值为x
Q->rear=(Q->rear+1)%QueueSize;//重新设置队尾指针
}
//元素出队列
intDeQueue(CirQueue*Q)
{
inttemp;
if(IsEmpty(Q))
{
printf("队列为空\n");//下溢,退出运行
exit
(1);
}
temp=Q->data[Q->front];//将队头的元素取出到temp里面
Q->count--;//队列元素个数减1
Q->front=(Q->front+1)%QueueSize;//循环意义下的头指针后移(即数组中第一个元素存放的位置的下标加1)
returntemp;
}
///////////////////方法
voidCirqueue(intnum,intCCC)
{
inti,start,count,j;
CirQueues;
for(start=1;start<=num;start++)//start为测试起点
{
Initial(&s);//初始化队列
for(i=1;i<=num;i++)//将所有士兵的编号依次进队
{
EnQueue(&s,i);
};
for(i=1;i{
j=DeQueue(&s);//删除队头结点
EnQueue(&s,j);//这两句是把队头的元素取出来然后放到队尾去,经过这个循环以后,要从那个开始的士兵的编号就会在队的队头位置
};
count=0;//删除结点数
while(count{
for(i=1;i{
j=DeQueue(&s);
EnQueue(&s,j);//这两句是把队头的元素取出来然后放到对尾
};//经过这个循环以后,队头的那个节点的值就是数到5对应的节点
j=DeQueue(&s);//把这个节点出队,但是没有在把它放到队尾,就相当于把它删除了
count++;
};//同第一个方法是一样,删除点数为m-1是结束循环
if(s.data[s.front]==1)break;//此时队只剩一个点,如果是排长就输出
}
cout<<"应从第:
"<}
////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////单向循环链表方法
voidOne_way(intM,intCCC)
{
//M为士兵个数
inti;
intstart,count;
lnode*l;
for(start=1;start<=M;start++)//start表示从哪个士兵开始数
{
//初始化链表
lnode*p=newlnode;//分配空间
l=p;//l为始终指向第一个节点的指针
l->num=1;//第一个节点代表的士兵编号赋值为1,至此第一个节点创建完毕
for(i=2;i<=M-1;i++)
{
lnode*q=newlnode;
q->num=i;
p->next=q;//创建其他节点,并将它接到链表尾部
p=q;//把指针p移后一位,使他指向刚链上的节点,也就是当前的最后一个节点
}
lnode*t=newlnode;//从这里开始创建最后一个节点
t->num=M;//节点编号为M
p->next=t;//连上去
p=t;
t->next=l;//并将最后一个节点与第一个节点相连,变成循环链表
//找到起点
p=l;//P指向第一个节点
for(i=1;i{
p=p->next;
};//一个一个往下找,一直到找到编号为start的那个节点,从这里开始计数
count=0;//删除的节点的个数
while(count{
for(i=1;i{
t=p;
p=t->next;
};//数到5就停下
t->next=p->next;//将该节点删除
count++;//删除结点的个数加1
p=t->next;//从下一个节点开始继续数
}//当删除的节点为M-1个时,就结束
if(p->num==1)
break;//此时表里面应该只有一个节点了,判断节点的编号是不是等于1,也就是是不是代表排长,如果是就结束循环
}
cout<<"应从第:
"<}///////////////////////////////////数组算法///////////////////////////////////数组算法
/////////////////////////////////////////////////////////////////////////