数据结构-递归和分治
递归和分治
斐波那契数
斐波那契数---递归实现
/*
斐波那契数列 1 1 2 3 5 8 ...
从第三个数开始每一个数都是前两个数之和
使用递归实现打印前40个斐波那契数
*/
# include<stdio.h>
# include<stdlib.h>
// 打印第i个斐波那契数
int fbnq(int n)
{
if(n <= 2) return 1;
else return fbnq(n - 1) + fbnq(n - 2);
}
int main()
{
for(int i = 1 ; i <= 40 ; i ++) printf("%d ",fbnq(i));
system("pause");
return 0;
}
斐波那契数---迭代实现
/*
斐波那契数列 1 1 2 3 5 8 ...
从第三个数开始每一个数都是前两个数之和
使用迭代实现打印前40个斐波那契数(注意这个是使用数组实现的)
*/
# include<stdio.h>
# include<stdlib.h>
int fbnqarr[1000];
int main()
{
fbnqarr[0] = 1;
fbnqarr[1] = 1;
int fbnqn = 0;
for(int i = 2 ; i < 40 ; i ++)
{
fbnqarr[i] = fbnqarr[i - 1] + fbnqarr[i - 2];
}
for(int i = 0 ; i < 40 ; i ++) printf("%d ",fbnqarr[i]);
system("pause");
return 0;
}
递归实现逆序输出
/*
使用递归实现输入一个任意长度的字符串,'#'表示结束输入
结束输入之后将刚才的字符串逆序输出
*/
# include<stdio.h>
# include<stdlib.h>
void nx_print()
{
char e;
scanf("%c",&e);
if(e != '#') nx_print();
printf("%c",e);
}
int main()
{
printf("请输入字符串!\n");
nx_print();
printf("\n");
system("pause");
return 0;
}
二分查找(分治)
/*binary search
二分查找
输入一个数列长度n,表示将输入一个长度为n的有序数列,接下来输入有序数列
输入想要查找的数字
输出查找的数字的位置
*/
# include<stdio.h>
# include<stdlib.h>
const int MAXSIZE = 110;
// 1 2 3 4 4 6
// 二分查找函数 传入想要查找的数字,顺序数列,结果位置的指针,数组的长度
void find(int x,int* arr,int *pos1,int *pos2,int n)
{
int l = 0 , r = n - 1;
while(l < r)
{
int mid = ( l + r ) / 2; // 注意每次mid都要更新,所以mid要写在while内
if(arr[mid] >= x) r = mid;
else l = mid + 1;
}
if (x != arr[l]) *pos1 = -1, *pos2 = -1;
else // 说明找到了左边第一个为x的数,但是这里还是有一种情况 1 2 3 4 4 5刚才只是找到了左边的4,右边的4的定位在使用一个二分(只是将check条件更改一下即可)
{
*pos1 = l;
l = 0 , r = n - 1;
while (l < r)
{
int mid = (l + r + 1) / 2;
if( arr[mid] <= x) l = mid;
else r = mid - 1;
}
*pos2 = l;
}
}
int main()
{
int n,e,findn;
int arr[MAXSIZE];
printf("输入有序序列长度:\n");
scanf("%d",&n);
printf("依次输入有序序列:\n");
for(int i = 0 ; i < n ; i ++)
{
scanf("%d",&e);
arr[i] = e;
}
printf("输入想要查找的数:\n");
scanf("%d",&findn);
int pos1 = -1 ,pos2 = -1;
find(findn,arr,&pos1,&pos2,n);
printf("想要查找的数在有序序列中的顺序依次为:");
printf("%d %d\n",pos1 + 1,pos2 + 1);
system("pause");
return 0;
}
汉诺塔问题
汉诺塔核心:
1.将A柱上的n-1个移动到B柱上
2.将A柱上的第n个移动到C柱上
3.将B柱上的n-1个移动到C柱上(这里就和1.2.开始递归就行)
/*
汉诺塔问题
有ABC三根柱子,A柱子上有个盘子
要把A柱子上的盘子移动到C柱子上,在移动过程中可以借助B柱子,但是要求小的盘子在上大的盘子在下。
要求输出入盘子的个数,输出需要移动的次数。
核心:
汉诺塔分为以下核心三步:
1.将A柱上n-1个移动到B柱上
2.将A柱上第n个移动到C柱上
3.将B柱上n-1个移动到C柱上(可以发现和第一步就相同了.....就这样递归下去就可)
*/
# include<stdio.h>
# include<stdlib.h>
int cnt;
// hanoimove函数 传入盘子的个数n,返回移动的次数
void hanoimove(int n,char a,char b,char c) // 将a柱上的盘子(借助b柱)移动到c柱上
{
if( n == 1)
{
// 移动A的最底下的一个盘子(这个整体中最大的盘子)通过B移动到C柱上
cnt ++;
printf("第%d次:将%c->%c上\n",cnt,a,c);
}
else
{
// 将A柱上N-1个盘子移动到B盘上
hanoimove(n-1,a,c,b);
cnt ++;
printf("第%d次:将%c->%c上\n",cnt,a,c);
// 将B柱上的n-1个盘子移动到C柱上
hanoimove(n-1,b,a,c);
}
}
int main()
{
int n;
printf("请输入A柱上盘子的个数:\n");
scanf("%d",&n);
char a = 'A',b = 'B', c = 'C';
hanoimove(n,a,b,c);
printf("一共移动了%d次\n",cnt);
system("pause");
return 0;
}
八皇后问题(递归回溯实现)
/*
八皇后问题(英文:Eight queens),是由国际象棋棋手马克斯·贝瑟尔于1848年提出的问题,是回溯算法的典型案例。
问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一
斜线上,问有多少种摆法
递归回溯方法:
思路:
0表示无,1表示这里放置了一个皇后
需要写一个isdanger函数用来判断该位置是否合法,find函数寻找下一个合法位置
把第一行的第一个位置放上皇后,使用find函数去寻找下一个合法位置,合法就放上1,继续find下一个合法位置,
八行都填满了(这个就是递归结束的条件),这时就找到了一种摆法。然后继续去往第一行第二个位置放皇后继续上述步骤..
*/
# include<stdio.h>
# include<stdlib.h>
int chess[8][8];
int cnt;
// 判断位置是否合法,传入位置(i,j)合法返回1,不合法返回0
// 即判断这一行的哪个列位置是合法的
int isdanger(int i , int j)
{
int f1 = 1, f2 = 1, f3 = 1, f4 = 1, f5 = 1;
// 判断这一列是否还有其他的皇后
for(int row = 0; row < 8 ; row ++)
{
if(chess[row][j])
{
f1 = 0;
break;
}
}
// 判断这个位置左上方是否有其他皇后
for(int row = i ,col = j ; row >= 0 && col >= 0 ; row --,col --)
{
if(chess[row][col])
{
f2 = 0;
break;
}
}
// 判断这个位置右上方是否有其他皇后
for(int row = i,col = j ; row >= 0 && col < 8 ; row --,col ++)
{
if(chess[row][col])
{
f3 = 0;
break;
}
}
// 判断这个位置左下方是否有其他皇后
for(int row = i ,col = j ; row < 8 && col >= 0; row ++,col --)
{
if(chess[row][col])
{
f4 = 0;
break;
}
}
// 判断这个位置右下方是否有其他皇后
for(int row = i ,col = j; row < 8 && col < 8 ; row ++,col ++)
{
if(chess[row][col])
{
f5 = 0;
break;
}
}
return (f1 && f2 && f3 && f4 && f5);
}
// 实现八皇后位置的查找与输出
void eigthqueenfind(int row)
{
if( row == 8 ) // row加到8就说明0-7 × 0-7 都已经完成了八皇后摆放
{
printf("第%d种\n", ++ cnt);
// 结束条件
for(int i = 0 ; i < 8 ; i ++)
{
for(int j = 0; j < 8 ; j ++)
{
printf("%d ",chess[i][j]);
}
printf("\n");
}
printf("\n");
}
else
{
for(int j = 0 ; j < 8 ; j ++) // 每一列都可以考虑到(由于这里是for循环然后递归,所以可以递归回溯)
{
// printf("判断(%d,%d)\n",row,j);
if(isdanger(row,j))
{
// printf("判断(%d,%d): 1\n",row,j);
chess[row][j] = 1; // 如果找到了这一行的某个列位置是合法的就把皇后摆放上去
eigthqueenfind(row + 1); // 这一行找到了就接着去寻找下一行
chess[row][j] = 0; // 找到了,或者没有找到都要将这个合法位置(row,j)重新设置成0,去寻找下一个
}
}
}
}
int main()
{
eigthqueenfind(0);
system("pause");
return 0;
}
rds_blogs