【C语言】带你玩转递归,迭代算法1

简介: 【C语言】带你玩转递归,迭代算法

前言

不像加减乘除,我们求学期间就已经见识过多次了,而大多数初学者在此之前可能都从未了解接触过递归思想,这使得很难上手递归算法,今天我希望能尽我所能结合画图已经例题的方法把递归算法讲解的通俗易懂,帮助大家入门


废话不多说了,我们开始今天的内容

一.什么是递归?

程序调用自身的编程技巧称为递归( recursion)。

递归做为一种算法在程序设计语言中广泛应用。 递归算法通常指一个过程或函数在其定义或说明中直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。

递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。(也就是说我们现在学的需要使用递归的场景大多数通过循环也能解决,在下面介绍的例子中会用循环也实现一遍)

递归的主要思考方式在于:把大事化小

当你在使用递归时遇到思考瓶颈,请牢记大事化小的思想!!

二.递归的两个必要条件

1.存在限制条件,当满足这个限制条件的时候,递归便不再继续。

2.每次递归调用之后越来越接近这个限制条件。

当你不满足这两个条件的任意一条时,程序会陷入死循环

当你的递归写出bug时,往往是没考虑上面这两个条件或者条件设置有误,调试时多想想递归条件最好能够画下图帮助自己理解。


三.配合实例讲解

打印整型数据的每一位

实例一:

接受一个整型值(无符号),按照顺序打印它的每一位。

例如:

输入:1234,输出 1 2 3 4


代码如下:

#include <stdio.h>
void print(int n)
{
if(n>9)//如果不大于9直接打印当前n的值即可
{
print(n/10);
}
printf("%d ", n%10);
}
int main()
{
int num = 1234;
print(num);
return 0;
}

我们想要把一个四位数甚至更多位的数每一位给剥离出来,首先要想到的是怎么得到每一位

我们知道,对10取余%就可以得到这个数的个位的数,而除以10就可以把这一位给消去,此时我们就可以这样实现(以下把n当作一个四位数举例)

先让n对10%得到此时这一位的数,然后将n/10来到下一位,再让n对10%得到这位数继续朝下进行直至n对10%等于0,说明此时n是个小于10的数只剩下它需要取了,取下它结束递归即可

画图解释

递归的递就是传递的意思,而归的意思是回归

fa73e68a67144951899245cbd43bb120.png

这就是递归!

解释完了递归在这段代码的应用,我们来讲讲这个代码中出现的问题

当我们中用户某天突发奇想输入了一个负数进去会发生什么呢?

61418d7a5d954fd185449c1edf39bda0.png

我们这个程序设定的条件是只针对正数的,要想输入一个负数也能打印就得这样修改代码

void print(int n)
{
  if (n > 9)//如果不大于9直接打印当前n的值即可
  {
    print(n / 10);
  }
  else if (n < -9)
  {
    print(n / 10);
  }
  printf("%d ", n % 10);
}
int main()
{
  int num = -1234;
  print(num);
  return 0;
}

或者把我们传入的int改为一个无符号整型

void print(unsigned int n)
{
  if (n > 9)//如果不大于9直接打印当前n的值即可
  {
    print(n / 10);
  }
  /*else if (n < -9)
  {
    print(n / 10);
  }*/
  printf("%d ", n % 10);
}

这里虽然都是非常简单的地方,但我想提醒大家的是,无论在递归或者任何其他程序的编写中我们都得尽可能考虑各方面的情况,在以后的程序猿工作中,我们要知道用户是不总是照着你的指示来使用程序的,我们得尽可能保证程序的避免上面这种bug。

循环实现

//判断输入数字位数
#include<math.h>
int Strlen(unsigned int n)
{
  int count = 0;
  while (n / 10)
  {
    count++;
    n /= 10;
  }
  return count;
}
void print(unsigned int n)
{
  int i = 0;
  int ret = Strlen(n);
  if (n > 9)
  {
    for (i = ret; i > 0; i--)
    {
      int m = pow(10, i);
      printf("%d ", n / m);
      n %= m;
    }
  }
  printf("%d", n);
}
int main()
{
  int num = 123456789;
  print(num);
  return 0;
}

我们先来看看效果

a9d18c96e5df4d0aa5d31f050d5d31e4.png


说实话,同样实现一个功能递归比循环简单多了,从代码的行数就能看出来。这就是我们使用递归算法的意义


求字符串长度

实例二

编写函数不允许创建临时变量,求字符串的长度。

#include <stdio.h>
int Strlen(const char*str)
{
if(*str == '\0')//是个空字符串
return 0;
else
    return 1+Strlen(str+1);//每次递归让Strlen朝后移动一位直至遇到"\0"不满足递归条件
}
int main()
{
char *p = "abcde";
int len = Strlen(p);
printf("%d\n", len);
return 0;
}

咱们还是画个图理解吧

3de357571fd4427f9d93f5aadea699fa.png


结合咱们这个图理解起来就比较简单啦,我希望以后你自己写的时候在有弄不清逻辑时也能画一个类似的图来理解。

循环实现

int Strlen(char* s)

int Strlen(char* s)
{
  int count = 0;
  while (*s != '\0')
  {
    count++;
    s++;
  }
  return count;
}
int main()
{
  char* p = "abcde";
  int len = Strlen(p);
  printf("%d\n", len);
  return 0;
}

结合咱们这个图理解起来就比较简单啦,我希望以后你自己写的时候在有弄不清逻辑时也能画一个类似的图来理解。

目录
相关文章
|
15天前
|
机器学习/深度学习 C语言
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
【8月更文挑战第5天】本篇文章用C语言采用多文件编写实现了一个基础的扫雷游戏(附源码),并讲解了关于函数递归的基础概念及其相对应的习题练习(附源码)
29 1
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
|
1天前
|
机器学习/深度学习 C语言
【C语言篇】递归详细介绍(基础概念习题及汉诺塔等进阶问题)
要保持最小的步数,每一次汉诺塔问题(无论是最初还是递归过程中的),如果此时初始柱盘子数为偶数,我们第一步是把最上面的盘子移动到中转柱,如果为奇数,我们第一步则是将其移动到目标柱。
【C语言篇】递归详细介绍(基础概念习题及汉诺塔等进阶问题)
|
6天前
|
算法
【算法】递归、搜索与回溯——汉诺塔
【算法】递归、搜索与回溯——汉诺塔
|
6天前
|
C语言
C语言中的递归
C语言中的递归
|
6天前
|
算法
【算法】递归总结:循环与递归的区别?递归与深搜的关系?
【算法】递归总结:循环与递归的区别?递归与深搜的关系?
|
6天前
|
算法
【算法】递归、搜索与回溯——简介
【算法】递归、搜索与回溯——简介
|
1月前
|
算法 Python
python中算法递归错误(Recursion Errors)
【7月更文挑战第18天】
25 1
|
11天前
|
存储 算法 Java
LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
31 0
|
2月前
|
机器学习/深度学习 算法 C语言
详细介绍递归算法在 C 语言中的应用,包括递归的基本概念、特点、实现方法以及实际应用案例
【6月更文挑战第15天】递归算法在C语言中是强大力量的体现,通过函数调用自身解决复杂问题。递归涉及基本概念如自调用、终止条件及栈空间管理。在C中实现递归需定义递归函数,分解问题并设定停止条件。阶乘和斐波那契数列是经典应用示例,展示了递归的优雅与效率。然而,递归可能导致栈溢出,需注意优化。学习递归深化了对“分而治之”策略的理解。**
46 7
|
3月前
|
搜索推荐 C语言 C++
【排序算法】C语言实现归并排序,包括递归和迭代两个版本
【排序算法】C语言实现归并排序,包括递归和迭代两个版本