• ベストアンサー

深さ優先探索について・・・

↓の文を参考にして、深さ優先探索のプログラムを書いてみました。 が、自分(初心者)ではできてるように思えたんですが、全然ダメみたいです。 再帰の使い方がよく分かってないというのもあるのですが(すみません)。 もしよろしければアドバイスを頂けませんか?お願いします! 『・始点(ここでは「1」)を出発して、番号が小さい順に進む位置を調べていき  行けるところ(辺でつながっていて、まだ未訪問の節点)まで進む。 ・行き場所が無くなったら、行けるところがある節点まで戻っ(再帰をリターンし) て再び進めるだけ進む。 ・行き場所がなくなったなら終了(再帰からリターン) プログラムの際に節点iから節点jへ進めるか否かは節点と枝の関係を表すテーブル(これを隣接行列と言う)の要素a[i][j]の値が1であり、かつ訪問フラグv[j]が0であった時です。 訪問フラグは初期値に0を入れ(未訪問を表す)、 節点jが訪問されたならv[j]に1を入れます』 #include<stdio.h> int recurse(int i,int j); int main(void){ int recurse(int i,int j); return 0; } int recurse(int i,int j){ int v[j]; int a[i][j]; v[j]=0; v[0]=0; a[i][j]={{0,1,1,0,0,0,0,0}, {1,0,0,1,0,0,0,0}, {1,0,0,1,0,0,0,0}, {0,1,1,0,1,0,0,0}, {0,0,0,1,0,1,0,1}, {0,0,0,0,1,0,1,0}, {0,0,0,0,0,1,0,1}, {0,0,0,0,1,0,1,0}}; for(i=0;i<8;i++){ for(j=0;j<8;j++){ if(a[i][j] == 1 && v[j] == 0){ v[j]=1; printf("%d->%d ",i,j); break; } else return 0; } } return 0; }

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

  • ベストアンサー
  • s2t
  • ベストアンサー率79% (47/59)
回答No.2

C言語の基礎から学んだ方がいいと思いますが、 こういうことでしょうか? #define N 8 char v[N] = { 0, 0, 0, 0, 0, 0, 0, 0 }; char a[N][N] = { { 0, 1, 1, 0, 0, 0, 0, 0 }, { 1, 0, 0, 1, 0, 0, 0, 0 }, { 1, 0, 0, 1, 0, 0, 0, 0 }, { 0, 1, 1, 0, 1, 0, 0, 0 }, { 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 1, 0, 1 }, { 0, 0, 0, 0, 1, 0, 1, 0 } }; void recurse(int i) { int j; printf(" %d", i+1); v[i] = 1; for(j = 0; j < N; j++) if(a[i][j] && !v[j]) recurse(j); } void dfs() { int i, cnt = 0; for(i = 0; i < N; i++) if(!v[i]) { printf("%d:", ++cnt); recurse(i); printf("\n"); } } int main(int argc, char *argv[]) { dfs(); return 0; }

kou_hana
質問者

お礼

お礼遅くなってすみませんm(_ _)m プログラムも書いていただいて、感謝しております。 参考にさせていただきました! ほんとうにありがとうございました!

その他の回答 (1)

  • hogeta
  • ベストアンサー率14% (4/28)
回答No.1

recursive functinの話以前に、関数の使い方や呼び方、 あと配列の宣言辺りが変ですよ。そこがきちんとできないと。 コンパイルの時点でエラーでません? あと、2次元配列を使った縦型探索は初めて見ますが、 個人的にはポインタと構造体を使ったもののほうが わかりやすいかと思います。

kou_hana
質問者

お礼

お礼遅くなってすみませんm(_ _)m 再帰に関して知識不足だったため、いちから勉強しなおしました。 時間をかけて作った結果、なんとかコンパイル・実行できました。 アドバイスありがとうございました!

関連するQ&A

  • 線形探索法のプログラムについて

    配列Aに格納されている数字を検索するプログラムより、 Aのプログラムでは配列Aに格納されている数字を検索(scanf("%d" , j)で入力)した にもかかわらず、「該当するデータがありませんでした」と表示されてしまいます。 Bのプログラムでは、配列Bに格納されている数字を検索(scanf("%d" , j)で入力)すると 「該当するデータがありました」と表示されます。 Aのプログラムで、------でかこってある部分に問題があると思われ、 いろいろと試してみましたが、未だにその理由をつかむことができません。 その理由を知りたく、書き込みを致しました。 ご教授の程宜しくお願い致します。 A. main(){ int i , j; int k = 0; int A[5] = {4 , 1 , 3 , 4 , 5}; printf("検索する数値を入力してください > "); scanf("%d" , j); --------------------------------------------------------------- for(i=0 ; i<5 ; i++){ if(A[i] == j){ printf("該当するデータはあります"); k++; } } --------------------------------------------------------------- if(k <= 0){ printf("該当するデータがありませんでした\n"); } return; } B #include<stdio.h> main(){ int i , j , k; int A[5] = {4 , 1 , 3 , 4 , 5}; printf("検索する数値を入力してください > "); scanf("%d" , j); for(i=0 ; i<5 ; i++){ if(A[i] == j){ k++; } } if(k>0){ printf("該当するデータはありました"); }else{ printf("該当するデータはありませんでした"); } return; }

  • 再帰呼び出しについて(基本)

    #include <stdio.h> void dan(int i); void kuku(void); void dan(int i) { int j; for (j = 1; j <= 9; j++) printf("%3d", i*j); putchar('\n'); } void kuku(void) { int i; for (i = 1; i <= 9; i++) dan(i); } int main(void) { kuku( ); return(0); } というプログラムがあるのですが、danとkukuを再帰呼び出しにしたいのですが、再帰の仕方がまったく分かりません。 知り合いに聞くと、両関数の引数を1つずつ増やすとよいと言われたのですが、手をつけられない状態です。 よろしくご教授お願いします。

  • 再帰関数とユークリッドの互除法を用いて最大公約数を求める

    学校の課題で、再帰関数とユークリッドの互除法を用いて10~100000までの最大公約数を求めるという問題が出て自分でプログラムを作ってみたのですが無限ループに入ったり、関数が使えてないみたいでできません。プログラムを見て頂いて、どこを改善したらいいかを教えてください。 #include <stdio.h> /* 正整数 n, m の最大公約数を計算する */ int gcd(int n, int m) { int res; res = n % m; if (res == 0) return m; /* 最大公約数が求まった */ return gcd(m, res); /* 再帰呼び出し */ } int main(void) { int i,j; for(i=10000;i>=10;i--){ for(j=10;j=10000;j++){ printf("%d to %d no saidaikouyakusuu ha %d \n", i, j, gcd(i, j)); } } return (0); } です。期限が今日の夜までで、ぎりぎりなんですがよろしくお願いします。

  • C言語 探索に関して

    C言語探索プログラムについて質問です。 #include <stdio.h> #define MAXSIZE 100 void swapData(int *x, int *y){ int tmp; tmp = *x; *x = *y; *y = tmp; } void simpleSort(int data[], int first, int last) { int i, j; for(i = first; i < last; i++){ for(j = i+1; j <= last; j++){ if(data[i] > data[j]) { swapData(&data[i], &data[j]); } } } } int ArrayBinarySearch(int data[], int n, int x) { int left = 0, right = n - 1, center; while(left <= right){ center = (left + right)/2; if(data[center]=x){ return center; }else if(x > data[center]){ left = center + 1; }else if(x < data[center]){ right = center - 1; } } return -1; } int main(int argc, char *argv[]) { int data[MAXSIZE]; int i, x; FILE *fp; scanf("%d", &x); fp = fopen(argv[1], "r"); for(i = 0; i < MAXSIZE; i++) { if (fscanf(fp,"%d", &data[i]) == EOF) break; } simpleSort(data, 0, i-1); printf("%d", ArrayBinarySearch(data, i, x )); return 0; } 数値が書かれたファイルを読み込んでソートした後に二分探索を行うプログラムをつくったのですが、うまく動きません。 どこがおかしいか教えてください。 お願いいたします。 ちなみに関数ArrayBinarySearchは目的の値が見つかれば配列中でのインデックスを、見つからない場合は-1を返す関数にしているつもりです。

  • ヒープの探索の再帰

    A[N]を利用したヒープのプログラムを作りました。 A[i]の親は、A[(i-1)/2]であるヒープです。 (上に行くほど小さい整数を格納) そしていまある整列されたヒープのなかからキーボードから入力した値xを検索する関数findを、 x ←検索する値 A[]←ヒープソートされた配列 n ←格納されているA[]の最後の添え字 として、 int find(int x, int *A, int i, int n) { if(A[i]==x){ printf("*\n"); /* ここの作業が行われているかを確認 */ return 1; } if(i>n)return 0; if(A[i]>x){ return 0; } else if (A[i]<x){ i = 2*i + 1; find(x, A, i, n); i++; find(x, A, i, n); } return 0; } というものを作ってみました。汚いかもしれませんが、とりあえず今はこれでいっぱいいっぱいです。 それで、当然のごとくうまくいきませんでした。 /**/内に書いたように、入力したxがヒープ内にある場合は「*」が一応表示されるのですが、どうもfindは1を返してくれません。0を返してしまいます。見つけた後もまだ再帰をくりかえしえしているようです。 どこがいけないのでしょうか。

  • 線形探索(番兵法)のプログラムについて。

    線形探索(番兵法)のプログラムについて考えています。 メイン関数からsearch関数に値を渡してそこで探索させるのですが、 int search(int a[], int n, int key) { int i = 0; a[n] = key; while (1) { if (a[i] == key) break; i++; } return (i == n ? -1 : i); } のwhileを使ったやり方からfor文を使ったやり方に変更したいと思っています。 色々な方法でプログラムを考えてみたいので。 そうすると、なんかうまくいきません。 for文だとどのように考えたらいいのでしょうか?

  • 二重ループのあるプログラム(C言語)

    #include <stdio.h> int main(void) { int i, j, c, c2; c = 0; for(i = 100; i < 1000; i++) { c2 = 0; for(j = 1; j <= i; j++) { if (i % j == 0) c2++; } if (c2 % 2 == 1) c++; } printf("%d個です。\n", c); return 0; } というプログラムがあるのですが、2重ループ部分のそれぞれのループに対応して、 2つの関数として独立させるとどのようになりますか? また、2つの関数のいずれにおいても、ループを用いずに再帰呼び出しを用いるとどうなりますか?

  • c言語の再帰で(関数呼び出し)+1がわからない

    再帰がどのように処理されているのか理解するために、再帰の時に +1 してみたところ 0! = 1 1! = 2 2! = 5 3! = 16 4! = 65 5! = 326 6! = 1957 7! = 13700 8! = 109601 9! = 986410 10! = 9864101 となりました。 普通の階乗の値を求めた最後に +1され、それが戻されると思ったのですが違いました。 これはどういう処理がされているのでしょうか? #include <stdio.h> int kaijo(int); int main() { int i; for (i = 0; i < 11; i++) printf("%d! = %d\n", i, kaijo(i)); return 0; } int kaijo(int n) { if (n == 0) return 1; else return n * kaijo(n - 1) + 1; }

  • C言語 2次元配列の積について

    <演習>  4行3列の行列と3行4列の行列の積を求めるプログラムを作成    せよ。各構成要素の値はキーボードから読み込むこと。  ここに出てくる「行列」とは、数学で出てくるあの「行列」のこと でしょうか。  そうなると私が作成したプログラムは意味が違ってきます。 4回同じ事をする様になっていて1回分の計算結果だけにしたいのですが、方法が分かりません。  入門レベルの知識しかありません。ご指導の程、お願いしたいで す。 下記、プログラムを送付します。 <プログラム> #include <stdio.h> int main(void) { int i,j=0; int o,p; int a[4][3]; int b[3][4]; int m[4][4]; for (i = 0;i < 4; i++){ for (j = 0; j < 3 ; j++) { printf("a[%d][%d] = ",i,j); scanf("%d",&a[i][j]); } } printf("\n"); for (i= 0; i < 3; i++){ for (j = 0; j < 4; j++){ printf("b[%d][%d] = ",i,j); scanf("%d",&b[i][j]); } } printf("\n"); for (o = 0; o < 4; o++){ for (p = 0; p < 4; p++){ for (j = 0; j < 4; j++){ for ( i=0 ; i < 4 ;i++ ) { m[o][p] = a[i][j] * b[i][j]; printf ("a[%d][%d] = %d ," ,i, j, a[i][j]); printf ("b[%d][%d] = %d ," ,i, j, b[i][j]); printf("m[%d][%d] = %d \n",o,p,m[o][p]); } } } } return 0; }    

  • c言語 行列のn階乗のプログラム

      1 2 -1 D= 3 0 -2   -1 1 2 の3次正方行列のn乗を計算するプログラムを作成しています。 いろいろと試してみましたがうまくいきません。 どなたか教えていただけるとうれしいです。 よろしくおねがいします。 #include <stdio.h> int main(void) { int a[3][3]={ {-1,2,-1},{3,0,-2},{-1,1,2} }; int b[3][3]={ {-1,2,-1},{3,0,-2},{-1,1,2} }; int s[3][3]; int m,n; int i,j,k; printf("[A]^n;n = ");scanf("%d",&n); for (m=2;m <= n;m++){ for (i=0;i<3;i++){ for (j=0;j<3;j++){ s[i][j] = 0; for(k=0;k<3;k++){ s[i][j] =s[i][j] + a[i][k] * b[k][j]; } } } for(i=0;i<3;i++){ for(j=0;j<3;j++){ b[i][j]=s[i][j]; } } printf("%3d",s[i][j]); putchar('\n'); } return (0); }

専門家に質問してみよう