反復と関数の再帰的学習

モジュラープログラムの最初の理解

実際のプログラムでは、カスタム関数は無料で呼び出され、対応するヘッダーファイルと関数定義インターフェイスも含まれています。そこで、簡単な加算関数を作成しました。
関数宣言

#ifndef __ADD_H__
#define __ADD_H__

//函数的声明
int Add(int x, int y);

#endif

このステートメントを、ディレクトリがadd.hであるファイルの下に置きます。

#ifndef __ADD_H__
#define __ADD_H__

#endif

目的は、関数が継続的に呼び出されたときに関数全体の定義セクションが継続的に実行されて、メインプログラムのコード量が大きくなりすぎるのを防ぐことです。関数呼び出しの原則は、関数定義ディレクトリ内のコードを、ヘッダーファイルを介して使用する必要のある場所に移動してから実行することです。
関数定義

int Add(int x, int y)
{
    return (x + y);
}

ディレクトリがadd.cであるディレクトリに配置し、対応する関数の関数をプロンプトの意味でディレクトリに配置します。これにより、他のユーザーとの連携が向上し、読みやすくなります。
メイン機能

#include <stdio.h>
#include "add.h"
int main()
{
    int a = 15;
    int b = 25;
    printf("sum=%d\n",Add(a, b));

    return 0;
}

カスタム関数のヘッダーファイルを引用するときは、二重引用符 ""を使用してください。

最も単純な再帰

#include <stdio.h>
int main()
{
    printf("haha\n");
    main();
    return 0;
}//递归常见的错误,栈溢出,stack overflow

これは無制限の再帰です。プログラムはしばらく実行すると自動的に停止し、警告ウィンドウがポップアップします。これは、プログラムの実行時に、実行時に生成されたローカル変数がスタックと呼ばれるメモリ領域に保存されるためです。制限はありません。の再帰、それ自体を呼び出し続ける、「ハハ」を印刷し続ける、それはスタックをいっぱいにします。
また、このプログラムも理解できます。再帰とは、関数を呼び出すことです。現在のインターネットの流行語を使用すると、一般に入れ子人形として知られています。

1234年に12 34を印刷する再帰関数を設計します

void print(int n)
{
    if (n > 9)
    {
        print(n / 10);
    }
    printf("%d ", n % 10);

}
#include <stdio.h>
int main()
{
    int num = 0;
    scanf("%d", &num);
    print(num);
    return 0;
}

初めて再帰を使用して特定の機能を実装する場合、教師が終了し、プログラムが入力され、デバッグが段階的に調整され、特にコードが1行ずつ実行されるのを監視していても、実際には非常に無知です。関数内の呼び出しです。最後のレベルでは、呼び出し条件が満たされない場合、プログラム実行ウィンドウが文字を1つずつ出力します。初期の段階では理解できませんでした。プログラムがレイヤーごとに実行される方法。戻ってみると、どこでプログラムが実行されているのか忘れてしまい、先生が絵を描いて説明してみると、一歩ずつ入っていくのがわかりました。最後のレイヤーが条件を満たさなくなり、実行が完了すると、ポップアップが完了し、前のレイヤーへのポップアップの後、次のステートメントが引き続き実行されます。

一時変数を作成せず、文字列の長さを見つけます

まず、再帰に関係なく、文字列の長さを実現できる関数を記述します。
もちろん、最も簡単なのは、ライブラリ関数を直接使用して文字列の長さを計算することです。

#include <string.h>
int main()
{
        strlen();
}

次に、カスタム関数を使用します

int my_strlen(char* str)
{
    int count = 0;
    while (*str != '\0')
    {
        count++;
        str = str + 1;
    }
    return count;
}

文字列全体を関数で直接呼び出すことはできません。文字列のアドレスを、文字列の最初の文字を指すポインタ変数としてのみ使用できます。呼び出しは関数に入ります。使用するたびに、「\」が表示されるまで+1します。 0 '文字、文字列の長さの計算が停止します。カウントは、文字列の長さを記録するためのカウントとして使用されます。しかし、必要なのは、この機能を実現するために一時変数を使用しない関数です。

#include <stdio.h>
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;
}

再帰は同じです。図を描くことで理解しやすくなります。プログラムの実行プロセスを視覚化して理解を深めます。特定の制限があり、関数を呼び出す各層により、制限がifステートメントを満たさないようになります。再帰的プロセスを停止します。一般的にストップドールとして知られています。

要因を見つけるための再帰と反復

前の2つの再帰的な例を理解した後、私は要因を見つけるためにこの再帰的なコードも独自に作成しました。一般的な考え方は、nを要求することです。、最初に(n-1)を要求してください!、(n-1)をお願いしたい!、最初に(n-2)を要求してください!、早送りして2をお願いしたい!、最初に1つ見つけてください!、それでも継続的に自分自身を呼び出しているので、コードは次のとおりです。

#include <stdio.h>
int Fac1(int n)
{
    int num = 1;
    int i = 0;
    for (i = 1; i <= n; i++)
    {
        num = i * num;
    }
    return num;
}
int Fac2(int n)
{
    int ret = 1;
    if (n != 0)
         ret = n * Fac2(n - 1);
    else
        return ret;
}
int main()
{
    int n = 0;
    scanf("%d", &n);
    printf("%d!=%d\n",n, Fac1(n));
    printf("%d!=%d\n",n, Fac2(n));
    return 0;
}

また、forループを使用して、目的を達成するための別の関数を記述しました。

n番目のFibonacciシーケンスを見つける

フィボナッチシーケンス、1 1 2 3 5 8 ...簡単に言えば、n番目を知りたい場合は、n-1番目とn-2番目を知る必要があり、n-1番目の合計を知る必要があります。 n-2番目の場合、n-2とn-3番目、n-3番目とn-4番目などを知る必要がありますが、n番目を再帰的に見つけるには、必要な操作の数は2 ^です。 n + 2 ^(n-1)+ ... + 2 ^ 2 + 2操作40回目以上になると、プログラムはすでに非常に明白な待機状態になっています。結果、計算回数を取得するには待機する必要があります。実際、それはすでに非常に大きく、n + 1ごとに、操作の数が2倍に増加し、操作時間が2倍に増加します。コードは次のとおりです。

#include <stdio.h>
int Fib1(int n)
{
    if (n <= 2)
        return 1;
    else
        return  Fib1(n - 1) + Fib1(n - 2);
}
int Fib2(int n)
{
    int a = 1, b = 1, c=0;
    int i = 0;
    if (n > 2)
    {
        for (i = 3; i <= n; i++)
        {
            c = a + b;
            a = b;
            b = c;
        }
        return c;
    }
    else
        return 1;
}
int main()
{
    int n = 0;
    scanf("%d", &n);
    int f2 = Fib2(n);
    printf("第%d个斐波那契数列:%d\n", n, f2);
    int f1 = Fib1(n);
    printf("第%d个斐波那契数列:%d\n", n, f1);
    return 0;
}

したがって、上記のコードには、再帰なしの反復によって実装される別の関数があります。実行すると、目標を達成するための2つの関数の時間差がわかります。したがって、再帰での関数呼び出しの数が多すぎると、計算量が膨大になります。 、目標を達成するために他の手段を使用する必要があります。

おすすめ

転載: blog.51cto.com/15078858/2593742
おすすめ