• ベストアンサー

プログラム構造の「再帰的」について

再帰的の説明に 「再帰的とは、あるプログラムがその内部から自分自身を呼び出して使用できる性質である。」「したがって再帰的であれば、必然的に再入可能でもある。」とありました。 ここで、「したがって再帰的であれば、必然的に再入可能でもある。」とは、つまり、プログラムAの中に再帰したプログラムA’が既に再入している状態にある、ということを表しているという理解かな?と思っているのですが、宜しいのでしょうか? より良い理解のために、補足説明などいただけたら、と思います。よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

言葉の問題になっちゃうんですが 再帰関数は、Aと言う関数があるとすれば A関数の実行途中にA関数を呼び出す記述があり 自分自身を呼びだす事になります。 一般的によくやるのが、ディレクトリーの処理ですね。

その他の回答 (3)

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.4

「再帰的であれば、必然的に再入可能でもある」 これは必ずしも正しくないんじゃないかという気がするんですけどねえ。 「再入可能」というのは、同一のプログラムを複数同時並行的に実行できることですよね。 再帰的なプログラムは、確かに呼び出す側と呼び出される側とで複数のプログラムを同時に 実行しているように見えます。しかし、「再入可能」という語を使う場合、通常は複数の 実行が非同期的になされることを前提としていると思うのです。No.3さんの回答にある 「オート変数のみ」という条件は、そのために必要なものです。しかし、再帰的なプログラム の場合、自分自身の呼び出しは一般的に同期をとって行われます。ですので、メモリーの 固定領域を参照していたとしても、動作に全く問題のない再帰的プログラムは可能です。 こうしたものを「再入可能」と呼んでよいのか、個人的には抵抗があります。

  • tttt23
  • ベストアンサー率25% (76/303)
回答No.3

> 「したがって再帰的であれば、必然的に再入可能でもある。」 この意味は、その関数が再入可能であるという性質を持っている必要があるということです。簡単に言えばオート変数だけ使って作られている必要があるということです。 再入可能でなければ再帰呼び出しはできません。従って再帰呼び出しをしているということは再入可能です。 ちなみに、A が B を呼び出し、B が A を呼び出すときも再帰呼び出しといいますので、必ずしも自分自身を (直接) 呼び出すわけではありません。

  • gookuma
  • ベストアンサー率33% (16/48)
回答No.2

特定の領域のメモリやI/Oポートを使用したプログラム・ルーチンは、マルチタスク環境や割り込みが発生する環境では正しく動作しません。 そこで、このような環境でも正常に動作するように作ったプログラム・ルーチンは再入可能であると言います。 再帰プログラム・ルーチンは、その内部で自分自身を呼び出しますが、これはプログラム・ルーチンの実行中に再度そのプログラム・ルーチンが呼び出されることなので、したがって再帰呼び出し可能なプログラム・ルーチンは再入可能なプログラム・ルーチンであるということが言えます。

関連するQ&A

  • 再帰的(リカーシブ)プログラムの説明について。

    以下は、再帰的(リカーシブ)プログラムの説明を記載しました。 この説明文でおかしい箇所の添削をお願い出来ないでしょうか? 宜しくお願い致します。 以下からになります。 再帰的(リカーシブ)プログラムとは、プログラムの中から自分自身を呼び出して実行することを再帰的(リカーシブ)アルゴリズムといい、この形式で再帰呼び出しを行うプログラムのこと。 まずは、再帰的アルゴリズムについて、例を使って説明を行いたい。 主プログラムとサブルーチンaがある。 主プログラムは、文字通り、主(メイン)となるプログラム。 サブルーチンは、主プログラムが呼び出して利用する処理をひとまとめにしたもの。 文字通り、サブとなる処理を行う。 主プログラムには、CALL aという命令が記述されている。 これはサブルーチンaを読み出すという命令。 この再帰的プログラムは、処理が終わったら、読み出された場所に帰っていく。 このため、戻り場所を記憶しておかないと帰る事が出来ない。 この戻り場所を記憶するのが、LIFO方式による記憶領域になる。 LIFO方式の記憶領域だから、スタック領域になる。 スタック領域だから、後入れ先出しで戻り場所を記憶していく。 まずは、1回目の呼び出しとして、主プログラムがサブルーチンaを呼び出している。 1回目の戻り場所を記憶しておく。 次にサブルーチンaを見ると、CALL a、つまり自分自身を読み出している。 これが2回目の読み出し。 このように自分自身を呼び出すことを再帰呼び出しという。 同じプログラムの中で自分自身を読み出しているのだが、コンピューターは、あたかも別のサブルーチンがあるように処理が行われている。 この場合、それぞれの処理で、別の変数を用意しながら処理を行う。 このサブルーチンで処理が終わった場合にも、もとに戻る必要がある。 これは2回目の呼び出しになるため、2回目の戻り場所を記憶しておく。 更に、3回目として再びサブルーチンaを呼び出す。 3回目の戻り場所を記憶し、また別の変数を用意しながら処理を行う。 ここで最後のサブルーチンで処理が終わったとする。 処理が終わったら、呼び出された場所に戻る。 戻り場所の記憶を見てみると、上から戻る順番に記録されていることがわかる。 戻り場所はLIFO方式、後入先出しで記録されているから、最後に呼び出した3回目の戻り場所が1番上に記録され、次に2、最後に1が記録されている。 最初は戻り場所を記憶した記憶領域を参照して、3回目に呼び出された場所に戻る。 ここで3の戻り場所が消える。 そして引き続き処理が行われる。 次に、2回目に呼び出した処理が終わり、2回目に呼び出された場所に戻り、2の戻り場所が消える。 また引き続き処理が行われ、1回目に呼び出した処理が終わり、1回目に呼び出された場所(主プログラム)に戻り、1の戻り場所が消える。 そして処理が行われ、プログラム全体が終了する。 このように、プログラムの中で自分自身を呼び出し、戻り場所を記憶しながら実行するようなプログラムを再帰的(リカーシブ)プログラムという。

  • プログラムの構成について

    構成上どれがいいんでしょうか? 1.複数のプロセスで同時に実行できるようにしたプログラムは再帰的である。 2.逐次再使用可能なプログラムは、再入可能でもある。 3.再入可能プログラムはを実現するためには、プログラムを手続き部分とデータ部分に分割して、データ部分をプロセスごとにもつ必要がある。 4.再帰的処理のためには実行途中の状態をFIFO方式で記録し、制御する必要がある。

  • 再帰的処理について

    指定したURLのページのHTMLを取得しその中のリンクを再帰的に表示するプログラムを考えていますが再帰的な処理の部分がよく理解できません。教えて下さい。お願いします。

    • ベストアンサー
    • Perl
  • 再帰プログラムで合ってるのか間違ってるのか

    関数zeromade()を作ってプログラムを完成させよ。 プログラムは与えられた値から、0までを順に出力するものである。 例えば、5を入力したら、 5 4 3 2 1 0 と出力されるものである。 ただし、リカーシブ(再帰)プログラムで作成すること。 (つまりfor文やwhile文は出てこない。) main内部を変更してはならない。 という問題があり #include <stdio.h> #include <stdlib.h> int zeromade(int); int main() { int n; scanf("%d", &n); if (n < 3) { fprintf(stderr, "3 ijou no atai wo nyuuryoku site kudasai\n"); exit(1); } zeromade(n); exit(0); } int zeromade(int x) { if(x < 0){ ; }else{ printf("%d\n",x); return (x * zeromade(x-1)); } } とやってこれが正解なのか不正解なのかわからないので質問させていただきます コンパイルすると 5を入力 5 4 3 2 1 0 と出ます 足りないことがあれば補足で説明します

  • 「再帰的に比較」とはどのような比較のことを言うのですか?

    「再帰的に比較」とはどのような比較のことを言うのですか? Linux diffコマンドのオプション[-r]の説明に「ディレクトリを比較するとき、見付かったサブディレクトリをすべて再帰的に比較する」とあります。「サブディレクトリをすべて比較する」なら分かるのですが「再帰的に」という意味が分かりません。理解を深めるためご教示お願いします。 再帰 ー 再帰(さいき)とは、あるものについて記述する際に、記述しているものそれ自身への参照が、その記述中にあらわれることをいう。定義において、再帰があらわれているものを再帰的定義という。(Wikipediaより)

  • プログラムを再帰的に実行させたい

    いつもお世話になっています。 ブログのトラックバック先のURLを取得するプログラムを作成しているのですが、 以下のようなプログラムを例において、 プログラムを再帰的に実行させたいです。 public class BlogTB { public static void main(String[]args){ String url1 = args[0]; String[] TBURL =HTMLTB.getHTMLtb(url1); for(int i=0;i<TBURL.length;i++){ System.out.println(TBURL[i]); } } HTMLTB.getHTMLtbでは、以前の質問の http://oshiete1.goo.ne.jp/kotaeru.php3?q=1725502 ご回答を参考にして作成した各ブログサービスごとに対応する トラックバック先のURLを取得する処理を行い、 HTMLをパースしてトラックバック先のURLを抽出し、 その一覧をTBURLに格納します。 例えば、ブログAの記事に、 B,C,D,E,Fのブログがトラックバックをしていたとすると、 上記のプログラムの結果として、ブログAのURLを入力すると、 B,C,D,E,FのブログのURLを表示するようになっています。 そこで、ブログAにトラックバックをしていたブログBにa,b,cのブログがトラックバックしていて、 同様にブログEにはd,eのブログがトラックバックをしていて、 さらにブログcにはブログ1,2がトラックバックをしていたとします。 このとき、B,C,D,E,FのブログのURLだけでなく、 a,b,cとd,eと1,2のブログのURLも取得したいと思っています。 つまり、プログラムを再帰的に動かして、 ブログAからたどれる全てのブログのURLを取得したいと思っています。 そのようにするには、上記のプログラムの中で、 どのような処理をさせればいいでしょうか? よろしくお願いします。

    • ベストアンサー
    • Java
  • 非末尾再帰について

    非末尾再帰を理解しようとすごく簡単なプログラムを書いてみたのですが、 どのように動作しているのかいまいち分かりません。 プログラムは以下のようなものです。 void rec(int n); int main(){ int n = 3; rec(n); } void rec(int n) { cout<<"AAA"<<n<<endl; if(n > 0){ n--; cout<<"BBB"<<n<<endl; rec(n); } cout<<"CCC"<<n<<endl; } 実行すると、出力は以下のようになりました。 AAA3 BBB2 AAA2 BBB1 AAA1 BBB0 AAA0 CCC0 CCC0 CCC1 CCC2 1回目のCCC0までは理解できますが、 そのあとなぜCCC0、CCC1、CCC2となるのか 分かりません。 そこが内部でどのように動作しているのか 説明していただけるとありがたいです。

  • 再帰呼び出しで求めたい経路を表示させたい!

    以前も「すべての経路を求めるには」というような質問をして再帰呼び出しにより無事解決することが出来ました。 しかし、少しわからないところがあります。 例えばaはb1とb2に接続されていてb1とb2はそれぞれc1,c2とc3,c4に接続されているとします。すべての経路は全部で4本ですね。 これを再帰呼び出しの中にprintf文を用いて表示させたところ a->b1->c1 c2 b2->c3 c4 というような感じで表示されたと思います。これは再帰呼び出しの性質で分岐があった以前の場所へ戻って探索を続けるからだというのは理解できました。しかし、実際は a->b1->c1 a->b1->c2 a->b2->c3 a->b2->c4 というように表示させたいです。何かこれを記憶するための変数が必要だと思うのですが、それを用いて上のように表示させるほう方法が思いつきません。 さらに、a->b2->c3というように特定の経路だけを選択して表示させたいです。アドバイスよろしくお願いします!

  • PythonVer3の再帰について

    現在、再帰について勉強しています。 関数のステートメントブロックの中に同じ関数を2か所使った場合の、処理される順番がよく解りません。 そこで、プログラムが表示されている状態で、Enterキーを押す毎に1行ずつ処理が進んで行き、今どの行が働いたかが分る様なソフト又は方法がないでしょうか。 よろしくお願いいたします。

  • 再帰の問題です。

    AOJの問題で、C言語で書いています。 ある解答者様のコードが自分の理解に深まると思い、見ているのですが、解答者様の作った関数のところの動作がよくわかりません。 問題です。 http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0030&lang=jp 解答例です。分かるところ、分からないところを書いていきます。 #include<stdio.h> int n,s,a;//グローバル変数。 void dfs(int i,int sum,int m){//ここでいう、i,sum,mが何を指しているのか分かりません。 if(m==0 && sum==s){a++;return;} if(i==10 || m==0)return; dfs(i+1,sum+i,m-1);/*再帰をしています。しかし、どうしてここに自分と同じ関数を2つ、入れている   のか、分かりません。あと、どうしてiを足したり、1引いた数を代入しているのでしょうか?*/ */ dfs(i+1,sum,m);   } int main(){ while(scanf("%d%d",&n,&s)!=EOF){//Ctrl+zを押さない限り、無限ループします。 if(n==0 && s==0)break;//問題文通り、2つとも0だったらループを表すwhileから抜けます。 a=0; dfs(0,0,n);//ここもわからないです。ただ、関数dfsの動きが分かれば、分かると思います。 printf("%d\n",a); } return 0; } 再帰は今苦戦していますので、ここでもっと理解を深め、自作関数で使えるようになりたいです。 長文失礼しました。 よろしくお願いします。