【十】递归

1、什么是递归?

  • 递归是一种数学上分而自治的思想
  • 递归将大型复杂问题转化为与原问题相同但规模较小的问题进行处理
  • 递归需要有边界条件
    • 当边界条件不满足时,递归继续进行
    • 当边界条件满足时,递归停止

2、利用递归,实现斐波拉契数列

什么叫斐波那契数列?
又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、……
即第n项是第n-1项与第n-2项的和;

完整代码:

/*
  该函数利用递归,实现斐波那契数列
*/
int fibonacci(int n)
{
  int iret = 0;
  if(n > 1)
  {
    iret = fibonacci(n - 1) + fibonacci(n - 2);
  }
  else
    if(n == 1)
    {
      iret = 1;
    }
    else
      if(n == 0)
      {
        iret = 0;
      }
  return iret;
}


int main()
{
  int i = 0;
  for(i = 1; i<=5; i++)
  {
    printf("%d\t",fibonacci(i));
  }
  printf("\n");
  return 0;
}

3、利用递归实现strlen函数

/*
  strlen的一般实现方法,循环累加
*/
int _strlen(char *s)
{
  int i = 0;
  if(s != NULL)
  {
    while(*s != '\0')
    {
      i++;
      s++;
    }
  }
  return i;
}

/*
  利用递归实现strlen函数
*/
int _strlen_1(char *s)
{
  int i = 0;
  if(s != NULL && *s != '\0' )
  {
    /*
      转换问题为下一个字符开始的字符串长度加上1,
      如此递归循环下去,直到上述条件不满足
    */
    i = _strlen_1(s +1) + 1;
  }
  return i;
}

int main()
{
  char *str = "abcdef";
  printf("%d\n",_strlen(str));
  printf("%d\n",_strlen_1(str));
  return 0;
}

4、汉诺塔递归解法

什么是汉诺塔?
有3根柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘,要求圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘,但可借助三根柱子中的其他柱子。

实现源码:

//核心思想是将问题拆分为n和n-1时的情况
//比如:如果有3圆盘个,那将问题拆分为,移动两个到b,还剩下一个,可直接移动到c
//然后再来解决移动这两个到b上的问题,它又会被拆分为移动一个到c上,剩下一个可直接移动到b
//然后将c上的一个直接移动到b
//最后再来解决b上的两个通过a移动到c,过程和上面类似

void hanoi(int n,char a,char b,char c)
{
  if(n > 0)
  {
    if(n == 1)
    {
      printf("%c-->>%c\n",a,c);
    }
    else
    {
      hanoi(n - 1,a,c,b);
      printf("%c-->>%c\n",a,c);
      hanoi(n-1,b,a,c);
    }
  }
}

int main()
{
  hanoi(6,'a','b','c');
  return 0;
}

5、全排列递归解法

什么叫全排列?
例如字符串:abc
那么它的全排列如下:
abc
acb
bac
bca
cba
cab

实现源码:

/*
  利用递归实现字符串
*/
int _strlen_1(char *s)
{
  int i = 0;
  if(s != NULL && *s != '\0' )
  {
    i = _strlen_1(s +1) + 1;
  }
  return i;
}

/*
  实现全排列
  参数s:指向被排序的字符数组指针
  参数b:开始位置
  参数e:结束位置
*/
void pre(char *s,int b, int e)
{
  //判断开始结束位置是否合法
  if((0 <= b) && ( b <= e))
  {
    //如果b == e,说明排序到最后一个字符了,可以输出本次的结果了
    //否则,还要就绪递归排序
    if(b == e)
    {
      printf("%s\n",s);
    }
    else
    {
      /*
      采取的算法是:字符串中b和e位置中间的字符串的每个字符都分别换位到首位b来,
      然后调用pre函数对剩下的b+1 -- e 字符串再排序,方法还是一样,将字符串
      中的首个字符都换位到首位,然后对剩下的进行排序,直到b和e中间的字符串只剩下一个
      字符,则表示一个排列成功,输出它;然后递归调用返回上一级递归函数,执行代码将被
      换位的字符还原,以备换位第二字符,依此类推
      */
      int i = 0;
      for(i = b;i<=e;i++)
      {
        //换位字符
        char c = s[b];
        s[b] = s[i];
        s[i] = c;

        //递归调用
        pre(s,b+1,e);

        //还原换位的字符
        c = s[b];
        s[b] = s[i];
        s[i] = c;
      }
    }
  }
}

int main()
{
  //注意,这里得使用字符数组,因为排序算法中需要修改值
  char str[] = "abc";
  pre(str,0,_strlen_1(str) - 1);
  return 0;
}

6、小结

  • 递归是一种将问题分而自治的思想
  • 用递归解决问题首先要建立递归的模型
  • 递归解法必须要有边界条件,否则将死循环
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值