diff --git a/docs/02advanced/04recursion/index.mdx b/docs/02advanced/04recursion/index.mdx new file mode 100644 index 000000000..e29ff7860 --- /dev/null +++ b/docs/02advanced/04recursion/index.mdx @@ -0,0 +1,416 @@ +--- +sidebar_position: 4 +--- + +import ViewSource from "@site/src/components/ViewSource/ViewSource"; +import Answer from "@site/src/components/Answer"; + +# 再帰 + +## 簡単な再帰関数 + +今回は、再帰関数を学んでいきます。 + +ではまずは、次の問題を考えてみましょう。 + +$a_1 = 1$、$a_n = a_{n - 1} + 1$ とします。このとき、$a_n$ を求めるプログラムを書いてください。 + +様々な方法が考えられます。 + +

解法 1

+ +この漸化式は、次のように数学的に解くことができます。 + +$$ +\begin{align*} + a_n &= a_{n-1} + 1 \\ + \therefore a_n &= a_1 + (n-1)\times 1 \\ + \therefore a_n &= n +\end{align*} +$$ + +よって、この結果を使えば次のように簡単に解けます。 + + + +

解法 2

+ +他には、次のようにして $a_1,a_2,a_3,\cdots$ のように順番に求めていくこともできます。 + + + +解法 1 のように数学的に解くことができればもちろん最も良いですが、数学的に解けないような場合は解法 2 のようにするしかなさそうです。しかし、解法 2 は漸化式の形とは少し見た目が違うため少し考えてから作らないといけません。 + +そのようなときに、再帰関数を使うとより簡単に書くことができます。(実は、再帰関数を使う以外の選択肢がないような場面もあります。) + +実際に、この問題を再帰関数を使って解いたプログラムを見てみましょう。 + + + +このプログラムを見ると、漸化式の形そのままですね。何も考えずに簡単に作ることができます。 + +さらに、このプログラムをよく見ると関数の中に関数が入っている形になっています。`a(n)` の値を求めるために `a(n - 1)` を使っています。さらに、`a(n - 1)` を求めるために `a(n - 2)` を使っています。これを繰り返していきますが、`a(1)` は `1` とわかっているので、そこで終了します。 + +```mermaid +flowchart LR + 5["a(5)"] -- 呼び出し --> 4["a(4)"] + 4["a(4)"] -- 呼び出し --> 3["a(3)"] + 3["a(3)"] -- 呼び出し --> 2["a(2)"] + 2["a(2)"] -- 呼び出し --> 1["a(1)"] +``` + +```mermaid +flowchart RL + 1["a(1)"] -- 1 --> 2["a(2)"] + 2["a(2)"] -- 2 --> 3["a(3)"] + 3["a(3)"] -- 3 --> 4["a(4)"] + 4["a(4)"] -- 4 --> 5["a(5)"] +``` + +再帰関数の作り方をまとめると、次のようになります。 + +1. 漸化式を立てて、自身を呼び出す。(例:$a_n = a_{n-1} + 1$ ) +1. 初期条件の処理を別に作っておく。(例:$a_1 = 1$ ) + +:::info + +再帰の定義を普通に書けば次のようになります。 + +> **再帰**(さいき 英:Recursion,Recursive)は、ある物事について記述する際に、記述しているもの自体への参照が、その記述中にあらわれることをいう。 フリー百科事典 Wikipedia より + +しかし、再帰の性質から次のように定義が書かれることもあります(笑) + +