cout<<"0";
cout<<"1";
t++;
for(t;t<9;t++)
cout<<"0";
cout<<"\n\t";
}
cout<<"\n";
}
//回溯递归法摆放皇后
voidPlaceQueen1(inti)
{
intj;
for(j=1;j<9;j++)//每个皇后都有8种可能位置
{
if((b[j]==0)&&(c[i+j]==0)&&(d[i-j]==0))//判断位置是否冲突
{
a[i]=j;//摆放皇后
b[j]=1;//宣布占领第J行
c[i+j]=1;//占领两个对角线
d[i-j]=1;
if(i<8)
PlaceQueen1(i+1);//8个皇后没有摆完,递归摆放下一皇后
else
print1();//完成任务,打印结果
b[j]=0;//回溯
c[i+j]=0;
d[i-j]=0;
}
}
}
voidPlaceQueen2(inti)
{
intj,e=1;
for(j=1;j<9;j++)
{
if((b[j]==0)&&(c[i+j]==0)&&(d[i-j]==0))
a[i]=j;
b[j]=1;
c[i+j]=1;
d[i-j]=1;
if(i<8)
PlaceQueen2(i+1);
else
print2();//打印结果
b[j]=0;//回溯
c[i+j]=0;
d[i-j]=0;
e++;
}
}
}
//调用主函数
voidmain()
{
……
cout<<"\n\n\t**WelcometoEightQueeninquiriessoftwareproblems**\n\n";
for(k=0;k<24;k++)//数据初始化
{b[k]=0;c[k]=0;d[k]=0;
}
ch='y';
while(ch=='y'||ch=='Y')
{
cout<<"\n\t查询菜单\n";
cout<<"\n\t******************************************************";
cout<<"\n\t*No.1--------每一行皇后放置的列数的情况*";
cout<<"\n\t*No.2--------视图矩阵形式显示皇后的位置*";
cout<<"\n\t*No.0--------退出*";
cout<<"\n\t******************************************************";
cout<<"\n\t请选择菜单号(No.0--No.2):
";
cin>>choice;
switch(choice)
{
case1:
cout<<"\n\t每一行皇后放置的列数的情况\n\n";
PlaceQueen1
(1);//从第1个皇后开始放置
break;
case2:
cout<<"\n\t使用回车查看下一种情况\n\n";;
PlaceQueen2
(1);//从第1个皇后开始放置
break;
case0:
ch='n';
break;
default:
cout<<"\n\t\t菜单选择错误,请重新输入!
\n";
}
}
}
四、调试分析及测试
4.1遇到的问题及解决方法
(1).由于对八个皇后放置的位置不能一次确定,而且前一个皇后的放置位置直接影响着后面的放置位置,使程序调试时要花费不少时间。
(2).本程序有些代码重复出现,显得程序的有些代码看起来很杂乱。
但其中最主要的问题是逻辑错误导致程序死循环或不循环或循环一小部分,但是编译时却没有错误,就是没有正确的输出答案。
比如说,在voidprint2()中有for(t;t<9;t++),如果赋t=1,则在视图显示法中会出现排序紊乱。
类似的还有出现死循环的问题,后在同学和老师的帮助下,经细心改正后才把调试工作做完。
(3).这里在编写回溯算法时候需要特别注意以下几点:
• 回溯循环的结束在于第一个皇后被回溯。
• 当找到一个解时,需要复制整个棋盘,不然接下来的回溯将破坏已经找到的解。
• 找到一个解后,需要在当前皇后的基础上回溯。
• 回溯一个皇后时,要对当前的列数进行重置。
一般在编写完核心代码后,需要编写一定的测试代码进行单元测试。
否则的话,后面出现的错误的程序代码问题是好难修正的!
4.2算法的时空分析
该算法的运行时间和和皇后的放置方法成正比,在最好情况下的时间和空间复杂度均为O
(1),在最差情况下均为O(n*n),平均情况在它们之间。
4.3程序模块构架
本程序模块划分比较合理,且利用指数组存储棋盘,操作方便。
至于整体的系统架构,为了简单起见,这样的系统可以分成两个模块,第一个模块是负责模拟问题、提供算法,而另外一个模块则致力于窗口演示,是一个窗体应用程序
4.4算法的改进
这道题可以用非递归循环也可以用递归循环的方法来做,这里我用了后者,其方法是分别一一测试每一种皇后摆法,直到得出正确的答案即所谓的回溯法。
4.5程序使用说明
(1)本程序的运行环境为DOS操作系统
(2)进入演示程序后即显示文本方式的用户界面
(3)进入界面后,就会提示输入字符串的输入形式,在八皇后求解程序中,只要你选择输出解的格式,选择1则显示为每一列皇后的放置的行数,,选择2则显示的是以矩阵形式形象的显示皇后的放置位置,选择3则退出程序的调试。
在调试结果中,1的位置也就表示了该皇后应该所在的位置,0代表了空位置。
4.6测试结果
初步运行界面
位置标明每一行皇后放置的列数
视图矩阵形式显示皇后位置
五、个人工作及创新
在本次课程设计的学习过程中,我在其中的最大的收获,就是得到了许多的经验以及软件设计的一些新的思路.
迈着时间的步伐,这次的课程设计也即将结束,但这个学期数据结构的学习还是具有相当大的意义,特别是这次的课程设计,它从一个程度上改变了我们的编程思想,如何将一个程序快速而又准备的进行编写,进行编译,都成为了我思考的重点,也通过这一个学期的学习,我们将数据结构的思想带入到了我们以后的编程学习中去。
在这个阶段,我也明白了,好的思想,不能提留于字面上的认知,还需要的是平时多练多写一些相关的程序,并且通过修改,加入新的算法去尝试改变自己的一些编程思想。
保持更新算法的速度,这才是关键。
比如说,八皇后在变成初期,由于不自觉的采用了非递归的算法,结果大大增加了程序的复杂程度,并且也让整个程序的时间复杂度变得更大.
在这次的八皇后问题中可以用概率算法,也可以采用传统的递归算法,这里我用了后者.而且还用到了回溯法.回溯法是允许我们在尝试某些选择失败后,能系统的尝试完所有可能的选择。
在八皇后问题中越早放置的皇后,她的选择就越多;而越晚放置的皇后,她的选择就越少。
八皇后问题和迷宫问题是很相似的,因此,若采用回溯,将能很好很快而且高效率的解决问题。
这便是在这次的一些创新之处!
当然还可以设计N皇后问题,基本思想不变
六、小结
通过这次的课程设计,我从中得到了许多经验和软件设计的一些新思路;从这个八皇后问题设计以及分析中,本人从中理解到了数据结构对于软件设计的重要性,它的使用,可以改变软件的运行周期,思路从繁化简,并且都能够通过其相关引导,将本身以前编程思想进行扩充,发展.这也是在这次课程设计中我所掌握得到的。
但在这次的课设中也遇了一些问题,如,八皇后在变成初期由于没真正体会到“树”在里面的运用,不自觉的采用了非递归的算法,结果大大增加了程序的复杂程度。
并且也让整个程序的时间复杂度变得更大;在重温了树的回溯,以及二叉树的遍历后,最终将程序进行了一次较大的改造。
并且通过思考,再将以前的数组知识加以运用才最终解决了这个问题,整个程序的算法的可看性也有了较大的改进。
参考文献
[1].黄晓霞,萧蕴诗.数据挖掘应用研究及展望[J].计算机辅助工程.2001.4:
23-29
[2].黄解军,潘和平,万幼川.数据挖掘技术的应用研究.计算机工程与应用,2003,02:
45~48.
[3].吕凤哲,C++语言程序设计(第二版).北京:
电子工业出版社,2005
[4].耿国华等著,数据结构——C语言描述,西安电子科技大学出版社
[5].苏仕华,数据结构课程设计.-北京:
机械工业出版社,2005.5
[6].严蔚敏,吴伟民,数据结构.北京:
清华大学出版社,1997
附录
致谢
在这次课程设计中,我遇到了不少问题,包括程序和课程设计的撰写上的,同学老师给了我许多帮助,在此我表示对你们的忠心感谢。
同时,学校给了我做课程设计的很好的条件,我才能够顺利的完成,在此,我仅以文字的形式表示忠心感谢,感谢您们对我的帮助。
#include
inta[8],b[8],c[30],d[30];
inti,k,X=0,Y=0;
voidprint1()
{
X++;
printf("\tNo.%d",X);//每一行皇后放置的列数的第X种情况
for(k=1;k<9;k++)
printf("%d",a[k]);
printf("\n");
}
voidprint2()
{
intt,n;
Y++;
printf("\tNo.%d",Y);//矩阵形式的第Y种情况
printf("\n\t");
for(k=1;k<9;k++)
{
n=a[k];
for(t=1;tprintf("0");
printf("1");
t++;
for(t;t<9;t++)
printf("0");
printf("\n\t");
}
printf("\n");
}
voidPlaceQueen1(inti)
{
intj;
for(j=1;j<9;j++)//每个皇后都有8种可能位置
{
if((b[j]==0)&&(c[i+j]==0)&&(d[i-j]==0))//判断位置是否冲突
{
a[i]=j;//摆放皇后
b[j]=1;//宣布占领第J行
c[i+j]=1;//占领两个对角线
d[i-j]=1;
if(i<8)
PlaceQueen1(i+1);//8个皇后没有摆完,递归摆放下一皇后
else
print1();//完成任务,打印结果
b[j]=0;//回溯
c[i+j]=0;
d[i-j]=0;
}
}
}
voidPlaceQueen2(inti)
{
intj,e=1;
for(j=1;j<9;j++)
{
if((b[j]==0)&&(c[i+j]==0)&&(d[i-j]==0))
{
a[i]=j;
b[j]=1;
c[i+j]=1;
d[i-j]=1;
if(i<8)
PlaceQueen2(i+1);
else
print2();//打印结果
b[j]=0;//回溯
c[i+j]=0;
d[i-j]=0;
e++;
}
}
}
voidmain()
{
intchoice,e=1;
charch;
printf("\n\n\t**WelcometoEightQueeninquiriessoftwareproblems**\n\n");
for(k=0;k<24;k++)//数据初始化
{
b[k]=0;
c[k]=0;
d[k]=0;
}
ch='y';
while(ch=='y'||ch=='Y')
{
printf("\n\t查询菜单\n");
printf("\n\t******************************************************");
printf("\n\t*No.1--------每一行皇后放置的列数的情况*");
printf("\n\t*No.2--------视图矩阵形式显示皇后的位置*");
printf("\n\t*No.0--------退出*");
printf("\n\t******************************************************");
printf("\n\t请选择菜单号(No.0--No.2):
");
scanf("%d",&choice);
switch(choice)
{
case1:
printf("\n\t每一行皇后放置的列数的情况\n\n");
PlaceQueen1
(1);//从第1个皇后开始放置
break;
case2:
printf("\n\t使用回车查看下一种情况\n\n");
PlaceQueen2
(1);//从第1个皇后开始放置
break;
case0:
ch='n';
break;
default:
printf("\n\t\t菜单选择错误,请重新输入!
\n");
}
}
}