【数据结构】(四)栈和递归(汉诺塔问题)
举例一个简单的的递归问题:
(一)汉诺塔说明:
分部解释:
汉诺塔问题代码:
#include <stdio.h>
void move(char c1, char c2)
{
printf("%c-->%c\n", c1, c2);
}
void hannoi(int n, char x, char y, char z) //不断进行递归调用,调用自身
{
if (n == 1)
{
move(x, z);
}
else
{
hannoi(n - 1, x, z, y);
move(x, z);
hannoi(n - 1, y, x, z);
}
}
int main()
{
int n;
printf("请输入盘子个数: ");
scanf_s("%d", &n); //一共多少个盘子
hannoi(n, 'A', 'B', 'C');
return 0;
}
(二)八皇后问题:(说明:)
一共十五条上对角线,所以设了d1[15]={};来表示,每条对角线是否有皇后占领,0表示没有,1表示有。(下对角线同理)
算法:
理解:教程八皇后 32:00 图解不懂就看,回溯是类似树的原理。
代码展示:
#include <stdio.h>
#include <stdbool.h>
/*八皇后问题*/
//公用变量数据初始化
int place[8] = { 0 }; //第n个皇后所占位置的列号,用来存储皇后位置,其他数组均是用来判断可放不
bool flag[8] = { 1,1,1,1,1,1,1,1 }; //标志数组,表示第col列1是否可占,1表示不冲突
bool d1[15] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }; //表示上对角线是否可占,因为棋盘共有14条上对角线
bool d2[15] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }; //表示下对角线是否可占,因为棋盘有14条下对角线
int number = 0; //用于统计解的数量(八皇后一共92个解)
//d1,d2里面的每一个数都表示一条对角线
void print();
void gernerate(int n);
int main()
{
gernerate(0);
return 0;
}
void gernerate(int n) //递归算法(栈),和,回溯算法(树)
{
int col;
for (col = 0; col < 8; col++)
{ //if判断是否可以放置皇后
if (flag[col] && d1[n - col + 7] && d2[n + col]) //flag【col】所在表示所在行和列标是相等的
{
place[n] = col; //第col行就相当于第n列的第col位置,在n行col列放皇后
flag[col] = false; //宣布占领第col列
d1[n - col + 7] = false; //占领两对角线
d2[n + col] = false;
if (n < 7)
{
gernerate(n + 1); //递归找出棋盘上八皇后位置
}
else
{
print();
}
//回溯算法,类似树的特性,回撤一步判断是否有其他新方案,没有再往回走,直到把所有方案写出
flag[col] = true;
d1[n-col+7] = true;
d2[n+col] = true;
}
}
}
void print() //打印结果,第n个皇后所占的列号
{
int col, i, j;
number++; //每打印一个结果,number++
printf("NO.%d\n", number);
int table[8][8] = { 0 }; //定义棋盘
for (col = 0; col < 8; col++)
{
table[col][place[col]] = 1; //将有皇后的地方改为1
}
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
printf("%d ", table[j][i]); //输出方案棋盘
}
printf("\n");
}
}