折半算法的解决完整文档.docx
《折半算法的解决完整文档.docx》由会员分享,可在线阅读,更多相关《折半算法的解决完整文档.docx(11页珍藏版)》请在冰豆网上搜索。
折半算法的解决完整文档
数据结构第二次上机作业
班级:
070921
姓名:
张玲玲
学号:
07092017
报告名称:
利用递归进行编程
上机时间:
2010年9月29日
报告时间:
2010年10月5日
实验目的:
深入了解函数的调用与返回;理解递归函数的执行过程;学会利用函数的执行过程。
实验方法:
利用把迭代公式翻译成代码和确定终止代码的方法,写出递归函数,从而执行程序。
实验结果:
程序运行成功,顺利得出结果。
题1:
八皇后问题
【在8*8的棋盘上放置八个皇后,要求这八个皇后相互不能攻击(同行,同列,斜线)】
一、问题重述:
八皇后问题要求在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击.按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子.
因此,八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。
而我的目的也是通过用C语言平台将一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击的92种结构予以实现. 使用递归方法最终将其问题变得一目了然,更加易懂。
二、算法描述:
A、数据初始化。
B、从n列开始摆放第n个皇后(因为这样便可以符合每一竖列一个皇后的要求),先测试当前位置(n,m)是否等于0(未被占领)。
如果是,摆放第n个皇后,并宣布占领(记得姚横列竖列斜列一起设置),接着进行递归;如果不是,测试下一个位置(n,m+1),但是如果当n<=8,m=8时,发现此时已无法摆放时,便要进行回溯。
从问题的某一种可能出发,搜索从这种情况能出发,继续搜索,这种不断“回溯”的寻找解的方法,称为“回溯法”。
C、使用数组实现回溯法的思想。
D、当n>8时,便打印出结果。
E、输出函数我使用printf输出,运行形式为:
第m种方法为:
********
算法流程图:
三、结构体变量说明:
intiCount=0;//!
记录解的序号的全局变量。
intSite[QUEENS];//!
记录皇后在各行上的放置位置的全局数组。
voidQueen(intn);//!
递归求解的函数。
voidOutput();//!
输出一个解。
intIsValid(intn);//!
判断第n个皇后放上去之后,是否有〉冲突。
四、函数说明:
解决冲突问题:
在这个问题中包括了行,列,两条对角线;
列:
规定每一列放一个皇后,不会造成列上的冲突;
行:
当第I行被某个皇后占领后,则同一行上的所有空格都不能再放皇后,要把以I为下标的标记置为被占领状态;
对角线:
对角线有两个方向。
在这我把这两条对角线称为:
主对角线和从对角线。
在同一对角线上的所有点(设下标为(i,j)),要么(i+j)是常数,要么(i-j)是常数。
因此,当第I个皇后占领了第J列后,要同时把以(i+j)、(i-j)为下标的标记置为被占领状态。
对于数据结构的实现,着重于:
数组a[I]:
a[I]表示第I个皇后放置的列;I的范围:
1..8;
对角线数组:
b[j](主对角线),c[j](从对角线),根据程序的运行,去决定主从对角线是否放入皇后;
五、程序执行结果:
六、遇到的问题:
当用printf输出时,出现了一些错误,几经调试后,发现原来是缺少了stdio.h这样一个头文件,添加了头文件后,还出现了一些问题,逻辑错误导致程序死循环或不循环或循环一小部分,但是编译时却没有错误,就是没有正确的输出答案,一开始我也不知道是怎么回事,通过和同学的交流,发现是逻辑错误,经过改正后,程序终于可以运行了.
七、附录:
程序源代码
#include
#include
#include
#include
#include
#defineQUEENS8
intiCount=0;//!
记录解的序号的全局变量。
intSite[QUEENS];//!
记录皇后在各行上的放置位置的全局数组。
voidQueen(intn);//!
递归求解的函数。
voidOutput();//!
输出一个解。
intIsValid(intn);//!
判断第n个皇后放上去之后,是否有冲突。
voidmain()
{system("title递归算法八皇后问题");
cout<<""<<"八皇后的解法:
"<cout<<""<<"-------------------------------------"<Queen(0);//!
从第0行开始递归试探。
getch();//!
按任意键返回。
}
voidQueen(intn)/*--Queen:
递归放置第n个皇后,程序的核心!
--*/
{inti;
if(n==QUEENS)//!
参数n从0到8试出一个解,将它输出并回溯。
{
Output();return;
}
for(i=1;i<=QUEENS;
{Site[n]=i;//!
在该行的第i行上放置皇后。
if(IsValid(n))//!
如果放置没有冲突,就开始下一行的试探。
Queen(n+1);
}
}
intIsValid(intn)/*判断第n个皇后放上去之后,是否合法无冲突。
*/
{inti;
for(i=0;i将第n个皇后的位置依次于前面n-1个皇后的位置比较。
{
if(Site[i]==Site[n])//!
两个皇后在同一列上,返回0。
return0;
if(abs(Site[i]-Site[n])==(n-i))//!
两个皇后在同一对角线上,返回0。
return0;}
return1;//!
没有冲突,返回1。
}
voidOutput()/*输出一个解,即一种没有冲突的放置方案。
*/
{
inti;
printf("No.%-5d",++iCount);//!
输出序号。
for(i=0;i依次输出各个行上的皇后的位置,即所在的列数。
printf("%d",Site[i]);
printf("\n");
}
题2:
折半查找
【用递归函数实现折半查找算法】
一、问题重述:
此程序即对于一个有序数列,满足s
(1)≤s
(2)≤…….≤s(n),写出查找关键字为key的数据的折半查找的算法。
首先将数列按有序化(递增或递减)排列,查找过程中采用跳跃式方式查找,即先以有序数列的中点位置为比较对象,如果要找的元素值小于该中点元素,则将待查序列缩小为左半部分,否则为右半部分。
通过一次比较,将查找区间缩小一半。
二、算法描述:
折半查找的基本思路:
先检查中间的数据是否是所需的数据,若不是则判断要查找的数据在中间数据的哪一边,下一次就在这个范围内查找。
1、首先确定整个查找区间的中间位置
mid=(a+b)/2
2、用待查关键字值与中间位置的关键字值进行比较;
若相等,则查找成功
若大于,则在后(右)半个区域继续进行折半查找
若小于,则在前(左)半个区域继续进行折半查找
3、对确定的缩小区域再按折半公式,重复上述步骤。
4、如果限定的范围中只剩下一个数(即起点、终点相同,a=b),而这个数等于key,则返回a,否则每查找到返回-1表示查找失败。
折半查找的存储结构可以用一维数组s[n]表示这个有序数列,数列的起点、终点分别为a和b。
三、结构体变量说明:
折半查找递归函数,如果查找成功,函数返回关键字所在位置,否则返回-1
定义了一个数组s[n]为有序数列,a、b分别为查找区间的起点和终点,key为查找关键字
四、函数说明:
1、定义了函数half()实现关键字与中间字的比较。
2、定义了sort()函数把输入的数值按升序排列。
3、定义了主函数voidmain(),实现递归调用half()函数。
五、程序执行结果:
1、请输入数据的个数(少于100):
5
请输入5个整数
3
15
26
35
21
按升序这5个数是:
315212635
请输入要查找的关键字:
36
关键字36没找到
2、请输入数据的个数(少于100):
6
请输入6个整数
31
27
2
44
53
按升序这5个数是:
227314453
请输入要查找的关键字:
44
关键字44已找到,位置是4
六、遇到的问题:
1、一开始把sort()函数放在了main()函数的后面,提示:
【toomanyargumentstofunction`voidsort()'】。
2、在main函数中错误的再次定义了sort函数。
七、附录:
#include
inthalf(ints[],inta,intb,intkey)
{
intmid;
if(a==b)
if(key==s[a])return(a);
elsereturn(-1);
else{
mid=(a+b)/2;
if(key
if(key>s[mid])return(half(s,mid+1,b,key));
if(key==s[mid])return(mid);
}
}
voidsort(inta[],intn)
{
inti,j,temp,p;
for(i=0;ip=i;
for(j=i+1;jif(a[j]temp=a[i];
a[i]=a[p];
a[p]=temp;
}
main()
{
inta[100],i,n,pos,key;
printf("\n请输入数据的个数(少于100):
");
scanf("%d",&n);
printf("\n请输入%d个整数\n",n);
for(i=0;iscanf("%d",&a[i]);
sort(a,n);
printf("\n按升序这%d个数是:
\n",n);
for(i=0;iprintf("%d",a[i]);
printf("\n请输入要查找的关键字:
");
scanf("%d",&key);
pos=half(a,0,n-1,key);
if(pos<0)
printf("\n关键字%d没找到!
\n",key);
else
printf("\n关键字%d已找到,位置是:
%d\n",key,pos);
}