九、递归和分治思想

来源:互联网 发布:义乌淘宝村 编辑:程序博客网 时间:2024/06/05 16:53

递归定义
在高级语言中,函数调用自己和调用其他函数并没有本质的不同,我们把一个直接调用自己或通过一系列的调用语句简介地调用自己的函数,称为递归函数。不过,每个递归定义必须至少有一个条件,当满足这个条件是递归不再进行,即函数不再调用自身而是返回。

经典递归问题:汉诺塔
这里写图片描述
问题描述:

  有一个梵塔,塔内有三个座A、B、C,A座上有诺干个盘子,盘子大小不等,大的在下,小的在上(如图)。
把这些个盘子从A座移到C座,中间可以借用B座但每次只能允许移动一个盘子,并且在移动过程中,3个座上的盘子始终保持大盘在下,小盘在上。
描述简化:把A柱上的n个盘子移动到C柱,其中可以借用B柱。

算法讨论:
定义函数move(n,x,y,z)表示把x上的n个盘子移动到z上,y为中间临时量
printf(x,z)表示把x上的盘子移到z上
最初需要解决的状态为:move(n,x,y,z)

状态1:先把x上的n-1个盘子移动到y上(暂时当做整体来看)
move(n-1,x,z,y)

中间状态:把x上剩的大盘子移动到z上
printf(x,z)

状态2:此时把y上的n-1个盘子移动到z上(操作结束后回到状态1)
move(n-1,y,x,z)

#include <stdio.h>//将n个盘子从x借助y移动到z void move(int n,char x,char y,char z){    if(1==n)    {        printf("%c-->%c\n",x,z);    }    else    {        move(n-1,x,z,y);//将n-1个盘子借助z移动到y上         printf("%c-->%c\n",x,z);//将第n个盘子从x移动到z上         move(n-1,y,x,z); //将n-1个盘子从y借助x移到z上     }} int main(){    int n;    printf("请输入汉诺塔的层数:");    scanf("%d",&n);    printf("移动的步骤如下:\n");    move(n,'X','Y','Z');    return 0;} 

八皇后问题
在8x8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
递归算法:

#include <stdio.h>int count=0;//判断是否危险,即行,列,斜线是否有棋子 int notDanger(int row,int j,int (*chess)[8]){    int i,k,flag1=0,flag2=0,flag3=0,flag4=0,flag5=0;    //判断列方向    for(i=0;i<8;i++)    {        if(*(*(chess+i)+j)!=0)        {            flag1=1;            break;        }    }     //判断左上方    for(i=row,k=j;i>=0&&k>=0;i--,k--)    {        if(*(*(chess+i)+k)!=0)        {            flag2=1;            break;        }    }     //判断左下方    for(i=row,k=j;i<8&&k>=0;i++,k--)    {        if(*(*(chess+i)+k)!=0)        {            flag3=1;            break;        }    }     //判断右上方    for(i=row,k=j;i>=0&&k<8;i--,k++)    {        if(*(*(chess+i)+k)!=0)        {            flag4=1;            break;        }    }     //判断右下方    for(i=row,k=j;i<8&&k<8;i++,k++)    {        if(*(*(chess+i)+k)!=0)        {            flag5=1;            break;        }    }     if(flag1||flag2||flag3||flag4||flag5)    {        return 0;    }    else    {        return 1;    }}//row 表示初始行数,n表示列数,int (*chess)[8]表示棋盘 每一行的指针 void EightQueen(int row,int n,int (*chess)[8]){    int chess2[8][8],i,j;    for(i=0;i<8;i++)    {        for(j=0;j<8;j++)        {            chess2[i][j]=chess[i][j];        }    }     if(8==row)//表示进行到第8行已经成功     {        printf("第 % d 种",count+1);        printf("\n");        for(i=0;i<8;i++)    {        for(j=0;j<8;j++)        {            printf("%d ",*(*(chess2+i)+j));        }        printf("\n");    }     printf("\n");    count++;    }     else//没有成功的时候     {        for(j=0;j<n;j++)        {            if(notDanger(row,j,chess))//判断是否危险            {                for(i=0;i<8;i++)                {                    *(*(chess2+row)+i)=0;//把棋盘置为0                 }                *(*(chess2+row)+j)=1;//不危险的位置存放1                EightQueen(row+1,n,chess2);             }         }    }   }int main(){    int chess[8][8],i,j;    for(int i=0;i<8;i++)    {        for(int j=0;j<8;j++)        {            chess[i][j]=0;        }    }     EightQueen(0,8,chess);    printf("总共有 %d 种解决方法!\n\n",count);    return 0;} 
0 0