1.再帰
プログラマーが自分自身と呼ぶプログラミング手法は、再帰と呼ばれます。再帰は、プログラミング言語でアルゴリズムとして広く使用されています。
1.プロセスまたは関数には、その定義または説明でそれ自体を直接または間接的に呼び出す方法があります。通常、大規模で複雑な問題を、元の問題と同様の小さな問題に再帰的に変換します。この戦略では、少量の問題を解決するプロセスで必要な複数の反復計算を記述するプログラム。これにより、プログラムのコード量が大幅に削減されます。
2.再帰についての主な考え方は、物事を小さくすること
です。2。再帰に必要な2つの条件
。1。制限があります。この制限が満たされると、再帰は続行されません
。2。各再帰呼び出しの後、次のようになります。この制限は、
たとえば次のとおりです。
演習1:
//接收一个整形值(无符号),按照顺序打印它的每一位,例如:输入1234,输出1 2 3 4
//解题思路:接收了一个1234,然后你先%10得到个位数4,然后在/10去掉个位数4,得到123,然后不断重复这个过程,在把这几个数字4 3 2 1 存起来,倒着打印出来。方法是可以的但是太过麻烦
//Print(123) 4
//Print(12) 3 4
//Print(1) 2 3 4 一位数字就没有必要继续拆下去了
void Print(int n)
{
if (n > 9) //存在限制条件
{
print(n / 10);
}
printf("%d ", n % 10); //无限接近结果
}
int mian()
{
unsigned int num = 0;
scanf("%d", num);
Print(num);
return 0;
}
演習2:
関数を記述して一時変数を作成し、文字列の長さを見つけることは許可されていません(文字列の長さを解決するためにstrlenの関数を記述することと同等です)
通常の解決方法:
①
int main()
{
char arr[] = "bit";
int len = strlen(arr);
printf("%d\n", len);
return 0;
}
②
//你会发现这个还是无法满足题目所说的要求,因为你写的函数内部创建了一个count的变量
int my_strlen(char* str)
{
int count = 0;
while(*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] = "bit";
int len = my_strlen(arr);
printf("len = %d\n", len);
return 0;
}
文字列の長さを見つけるために再帰的な方法を使用する
int my_strlen(char* str)
{
if (*str != '\0')
return 1 + my_strlen(str + 1);
else
return 0;
}
int main()
{
char arr[] = "bit";
int len = my_strlen(arr);
printf("len = %d\n", len);
return 0;
}
//大事化小
//my_strlen("bit")
//1 + my_strlen("it")
//1 + 1 + my_strlen("t")
//1 + 1 + 1 + my_strlen("")
//1 + 1 + 1 + 0
//3
//*str != '\0' 是限制条件,当不满足时就会不再进行递归,结果在不断地接近目标
演習3:nの階乗を見つける
1.ループでそれを実現する
int Fac1(int n)
{
int i = 0;
int ret = 1;
for (i = 1; i <= n; i++) //n! 不好想我们可以倒着思考问题 1*2*3 ....*n
{
ret *= i;
}
return ret;
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
ret = Fac1(n); //循环的方式
printf("%d\n", ret);
}
2.達成するための再帰的な方法
int Fac2(int n)
{
if (n <= 1)
return 1;
else
return n*Fac2(n - 1);
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
ret = Fac2(n);
printf("%d\n", ret);
}
演習
4n番目のフィボナッチ数を見つけます(最初の2つの数の合計は次の数に等しい)
int Fib(int n)
{
if (n <= 2)
return 1;
else
return Fib(n - 1) + Fib(n - 2);
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
//TDD --- 测试驱动开发 先想这个函数怎么用,再去具体实现这个函数
ret = Fib(n);
printf("ret = %d\n", ret);
return 0;
}
この再帰的な方法で実装された関数は、nが比較的小さい場合に迅速かつ正確に結果を得ることができますが、nが50などの大きくなると、結果が長時間表示されないことがわかります。
50
49 48
48 47 47 46
47 46 46 45 46 45 45 44
你会发现在做很多重复的工作
したがって、ここでフィボナッチ数を解くために再帰的な方法を使用することは適切ではありません。再帰を使用するほど簡単ではありません。したがって、ここではループを使用して達成します。
int Fib(int n)
{
int a = 1;
int b = 1;
int c = 1; // 这里在初始化的时候你可能会初始成0;但是当n等于1或者2的时候你进来不满足while循环直接返回c那就错了
while (n > 2)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
ret = Fib(n);
printf("ret = %d\n", ret);
return 0;
}
要約:しかし、問題を再帰的に解決する場合、制限を同時に満たし、常に目標値に近づけることは正しくありません。この場合、スタックオーバーフローが発生し、運用効率が極端に低下する可能性があるためです。
void test(int n)
{
if (n < 10000)
{
test(n + 1);
}
}
int main()
{
test(1);
return 0;
}
//栈溢出了,程序崩溃
改善:1。ハノイの塔の問題
2.カエルのジャンプの問題