数据结构课程设计-农夫过河-实验报告.
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、需求分析描述
1、针对实现整个过程需要多步,不同步骤中各个事物所处位置不同的情况,可定义一个结构体来实现对四个对象狼、羊、白菜和农夫的表示。
对于起始岸和目的岸,可以用0或者1来表示,以实现在程序设计中的简便性。
2、题目要求给出四种事物的过河步骤,没有对先后顺序进行约束,这就需要给各个事物依次进行编号,然后依次试探,若试探成功,进行下一步试探。
这就需要使用循环或者递归算法,避免随机盲目运算且保证每种情况均试探到。
3、题目要求求出农夫带一只羊,一条狼和一颗白菜过河的办法,所以依次成功返回运算结果后,需要继续运算,直至求出结果,即给出农夫的过河方案。
4、输出界面要求具有每一步中农夫所带对象及每步之后各岸的物体,需要定义不同的数组来分别存储上述内容,并使界面所示方案清晰简洁。
二、系统架构设计
1.设计中首先涉及的就是数据类型的定义,首先,定义一个结构体用来存放农夫、狼、羊、白菜的信息。
具体定义为:struct Condition
{
int farmer;
int wolf;
int sheep;
int cabbage;
};
定义了一个结构体数组Condition conditions[100],定义状态数组用来记录他们过河的状态0:起始岸;1:目的岸;
程序中定义的char action100数组用来存放各个物件以及人过河或返回的说明语句。
2.程序中定义的子函数有:
2.1 将狼带到目的岸以及带回起始岸的函数takeWolfOver()和takeWolfBack ();
takeWolfOver()函数中将conditions[i+1].wolf=1,白菜、羊的状态不变,
同时要有action[i]=" take wolf over."将狼带到目的岸语句;
takeWolfBack()函数中将conditions[i+1].wolf=0,白菜、羊的状态不变,同时要有action[i]=" take wolf back."将狼带回起始岸语句。
2.2 将羊带到目的岸以及带回起始岸的函数takeSheepOver()和takeSheepBack();
takeSheepOver()函数中将conditions[i+1].sheep=1,白菜、狼的状态不变,同时要有action[i]=" take sheep over."将羊带到目的岸语句;takeSheepBack()函数中将conditions[i+1].sheep=0,白菜、狼的状态不变,同时要有action[i]=" take sheep back."将羊带回起始岸语句。
2.3 将白菜带到目的岸以及带回起始岸的函数takeCabbageOver和takeCabbageBack();
takeCabbageOver()函数中将conditions[i+1].cabbage=1,羊、狼的状态不变,同时要有action[i]=" take cabbage over."将白菜带到目的岸语句。
takeCabbageBack();函数中将conditions[i+1].cabbage=0,羊、狼的状态不变,同时要action[i]=" take cabbage back."将白菜带回起始岸语句。
2.4 getOverBarely()函数是用来完成一个人单独过河的操作,调用该函数时action[i]=" get over barely."赋值人单独回到目的岸,狼、羊、白菜的状态保持不变。
2.5 getBackBarely()函数是用来完成一个人单独回到起始岸的操作,调用该函数时action[i]=" get back barely."赋值人单独回起始岸,狼、羊、白菜的状态保持不变。
2.6 输出过河的每一个步骤以及完成每一步之后人、狼、羊、白菜的状态这一动作是由showResult()函数来完成的,
2.7 tryOneStep是本次设计的核心程序,上面提到的所有子程序之间都是相互独立的,但是在tryOneStep函数中都要调用上面的子函数。
3.程序流程图:
3.1
图1. 主函数的流程
3.2tryOneStep函数工作的流程图如下:
图2.tryOneStep ()函数的流程
三、系统实现过程
编写好各个子程序后,在main ()函数中首先将人,狼,羊,白菜的初始状态
都置为0,接下来调用tryOneStep ()函数,同时0作为实参传给tryOneStep
()函数。
1. tryOneStep ()函数实现过程如下:
1.1 首先,定义两个int 型变量c ,j 。
1.2接下来判断四者的状态是否都为1,若都为1说明已经过河成功了,之后调
用showResult ()函数,输出相关信息,在由return 返回到调用处。
程序执行
结束。
1.3再判断是否有非法情况出现,即:羊单独和白菜在一起或狼和羊单独在一起,
具体实现的语句
if(conditions[i].farmer!=conditions[i].wolf&&conditions[i].wolf==cond
itions[i].sheep||
conditions[i].farmer!=conditions[i].sheep&&conditions[i].sheep==condi tions[i].cabbage)
{
return;
} 如果条件成立的话执行if语句即执行return 返回到调用点,否则,向下继续执行。
1.4 再通过 for(c=0;c<i;c++)
{
if(conditions[c].farmer==conditions[i].farmer&&
conditions[c].wolf==conditions[i].wolf&&
conditions[c].sheep==conditions[i].sheep&&
conditions[c].cabbage==conditions[i].cabbage)
{
return;
}
} 判断是否有重复状态
1.5 j=i+1
1.6判断conditions[i].farmer是否为0,如果不为0,则跳转到(1.10)接着执行;若为0,则设置为1,调用getOverBarely(i),接着tryOneStep(j),调用tryOneStep(j)时就是重复执行整个调用过程,直到其中有条件不成立时跳到该调用处。
1.7 执行1.6以后跳回到调用点后,接着判断狼是否还未过河。
即conditions[i].wolf==0是否成立,成立则调用takeWolfOver(i),再执行tryOneStep(j)递归调用自身但实参已发生变化,直到退回到该调用处,就继续向下执行;若狼已经过河就执行1.9。
1.8判断羊是否还未过河。
即conditions[i].sheep==0是否成立,若过河,则就执行1.9;未过河,则调用takeSheepOver(i),再执行tryOneStep(j)。
1.9最后判断白菜是否已经过河,未过河则调用takeCabbageOver(i),再tryOneStep(j),完成调用后回到该调用处。
1.10若开始conditions[i].farmer=1,则从1.10这里就开始执行,先将conditions[i].farmer设置为0,接着调用getBackBarely(i),后执行tryOneStep(j),递归调用,直到退回该处,接着向下执行。
1.11顺序执行conditions[i].wolf==1若成立就执行 takeWolfBack(i)后tryOneStep(j),直到退回到该调用处,若不成立就直接向下执行。
1.12顺序执行conditions[i].sheep==1若成立就执行 takeSheepBack(i)后tryOneStep(j),直到退回到该调用处,若不成立就直接向下执行。
1.13顺序执行conditions[i].cabbage==1若成立就执行 takeCabbageBack(i)后tryOneStep(j),直到退回到该调用处,若不成立就直接向下执行。
2.主函数调用关系如下:
图3.函数调用关系
四、总结和体会
1.刚开始在判断每一种是否安全时走得有点麻烦:开始把每种状态都列出来逐个判断,可时间复杂度较大,经过考虑只要判断两大类即可,第一种是农夫和羊一块,然后再分析其他两种物体的状态。
第二种是两者不在一起,然后再分析其他两种物体的状态。
这样可以很快找出安全状态而且降低了时间复杂度。
2.对本次实验,我得到:以前用c或c++编程,只是注重如何编写函数能够完成所需要的功能,似乎没有明确的战术,只是凭借单纯的意识和简单的语句来堆砌一段程序。
但现在学了《数据结构》后,变成完全不同啦,在编写一个程序之前,自己综合考虑各种因素,首先选取自己需要的数据结构,然后选一种或几种存储结构来具体决定后面的函数主要风格。
3.这次用状态回溯算法,其中主要是递归,以前都不敢用这个,这次尝试着,一步一步都克服啦,这都是很大进步。
五、参考文献
(1)严蔚敏吴伟民,数据结构(C语言版)清华大学出版社2011.7
(2)徐孝凯数据结构使用教程清华大学出版社1999.12 六、开发环境
VC6.0
七、源代码
//main.cpp
#include"farmerwade.h"
int main()
{
cout<<" 数据结构课程设计"<<endl;
cout<<" ****************"<<endl;
cout<<" 农夫过河"<<endl;
conditions[0].farmer=0;
conditions[0].wolf=0;
conditions[0].sheep=0;
conditions[0].cabbage=0;
tryOneStep(0);
getchar();
return 0;
}
//farmerwade.h
//定义一个结构体用来存放农夫、狼、羊、白菜的信息
#include <iostream>
using namespace std;
struct Condition
{
int farmer;
int wolf;
int sheep;
int cabbage;
};
//定义状态数组用来记录他们过河的状态0:起始岸;1:目的岸Condition conditions[100];
char* action[100]; // 存放各个物体及农夫过河或返回的情况
//产生某个动作之后再状态更新
void takeWolfOver(int i)
{
action[i]=" take wolf over.";
conditions[i+1].wolf=1;
conditions[i+1].sheep=conditions[i].sheep;
conditions[i+1].cabbage=conditions[i].cabbage;
}
void takeWolfBack(int i)
{
action[i]=" take wolf back.";
conditions[i+1].wolf=0;
conditions[i+1].sheep=conditions[i].sheep;
conditions[i+1].cabbage=conditions[i].cabbage;
}
void takeSheepOver(int i)
{
action[i]=" take sheep over.";
conditions[i+1].wolf=conditions[i].wolf;
conditions[i+1].sheep=1;
conditions[i+1].cabbage=conditions[i].cabbage; }
void takeSheepBack(int i)
{
action[i]=" take sheep back.";
conditions[i+1].wolf=conditions[i].wolf;
conditions[i+1].sheep=1;
conditions[i+1].cabbage=conditions[i].cabbage; }
void takeCabbageOver(int i)
{
action[i]=" take cabbage over.";
conditions[i+1].wolf=conditions[i].wolf;
conditions[i+1].sheep=conditions[i].sheep;
conditions[i+1].cabbage=1;
}
void takeCabbageBack(int i)
{
action[i]=" take cabbage back.";
conditions[i+1].wolf=conditions[i].wolf;
conditions[i+1].sheep=conditions[i].sheep;
conditions[i+1].cabbage=0;
}
//农夫单独来回
void getOverBarely(int i)
{
action[i]=" get over barely.";
conditions[i+1].wolf=conditions[i].wolf;
conditions[i+1].sheep=conditions[i].sheep;
conditions[i+1].cabbage=conditions[i].cabbage;
}
void getBackBarely(int i)
{
action[i]=" get back barely.";
if(i>=100)
{
cout<<"index reached 100,something is wrong!"<<endl;
return ;
}
conditions[i+1].wolf=conditions[i].wolf;
conditions[i+1].sheep=conditions[i].sheep;
conditions[i+1].cabbage=conditions[i].cabbage;
}
void showResult(int i)
{
int c;
for(c=0;c<i;c++)
{
cout<<c+1<<"."<<action[c]<<endl;
}
cout<<endl<<"All came to the other side!"<<endl;
}
void tryOneStep(int i)
{
int c,j;
//到达成功状态
if(conditions[i].farmer==1&&
conditions[i].wolf==1&&
conditions[i].sheep==1&&
conditions[i].cabbage==1)
{
showResult(i);
return;
}
//到达非法状态
if(conditions[i].farmer!=conditions[i].wolf&&conditions[i].wolf==conditions[i].sheep||
conditions[i].farmer!=conditions[i].sheep&&conditions[i].sheep==conditions[i].cabbage) {
return;
}
//判断是否有重复状态
for(c=0;c<i;c++)
{
if(conditions[c].farmer==conditions[i].farmer&&
conditions[c].wolf==conditions[i].wolf&&
conditions[c].sheep==conditions[i].sheep&&
conditions[c].cabbage==conditions[i].cabbage) {
return;
}
}
j=i+1;
if(conditions[i].farmer==0)
{
conditions[j].farmer=1;
getOverBarely(i);
tryOneStep(j);
if(conditions[i].wolf==0)
{
takeWolfOver(i);
tryOneStep(j);
}
if(conditions[i].sheep==0)
{
takeSheepOver(i);
tryOneStep(j);
}
if(conditions[i].cabbage==0)
{
takeCabbageOver(i);
tryOneStep(j);
}
}else
{
conditions[j].farmer=0;
getBackBarely(i);
tryOneStep(j);
if(conditions[i].wolf==1)
{
takeWolfBack(i);
tryOneStep(j);
}
if(conditions[i].sheep==1)
{
takeSheepBack(i);
tryOneStep(j);
}
if(conditions[i].cabbage==1)
{
takeCabbageBack(i);
tryOneStep(j);
}
}
}。