0

次の問題があります: file1.dat と file2.dat の 2 つのファイルがあり、それぞれ列に 9 つの数字が入っています。例えば:

file1.dat = 1,1,1,2,2,4,4,4,7

file2.dat = 2,4,7,3,4,1,3,7,1

このネットワークでトライアドを見つけるプログラムを作成しようとしました。トライアドとは、この番号の 1 つで始まる 3 つの番号のグループを意味し、一緒にリンクされている別の 2 つに渡され、元の番号に戻ります。 . この場合、file1.dat は開始する「ノード」を記述し、file2.dat は到着するノードを記述します (1->2、1->4、1->7、2->3 ... )。この小さな「ネットワーク」には 2 つのトライアドがあり、1,2,4 と 1,4,7 で構成されています。次のプログラムを書きました。

#include <stdio.h>
#include <stdlib.h>
#define N 9

int main (void){

int A[N],B[N],i,j,l,m,k;
int x,y;
int valueA,valueB,count,middle_value,new_value;
FILE *fp,*fq;

if ((fp = fopen("file1.dat", "r")) == NULL ) {
  printf("Error opening file 1\n");
  exit(EXIT_FAILURE);
  } 

for (i = 0; i < N; i++) {
    fscanf(fp,"%d", &x);
    A[i] = x;
  }

  if ((fq = fopen("file2.dat", "r")) == NULL ) {
    printf("Error opening file 2\n");
    exit(EXIT_FAILURE);
  } 

  for (i = 0; i < N; i++) {
    fscanf(fq,"%d", &y);
    B[i] = y;
  }

up コードは、2 つの配列 A と B に 2 つのファイルのすべてのデータを格納するために使用されます。

  for (i=0;i<N;i++){      

    valueA=0;
    valueB=0;     

    valueA=A[i];
    valueB=B[i];
    count=0;
    middle_value=0;
    new_value=0;

//Start the research of the first node of the file2.dat in the file1.dat

 for(k=i+1;k<N;k++){

  if(A[k]==valueB){

    count++;

ここに、最初の参加ノードと同じ値を持つ数値が最初のファイルで見つかった場合に通知する、1 に増加するカウンター「カウント」を配置します。ここで、カウンター = 1 の場合、コンピューターに valueB = A[k] を記憶させ、トライアドの中間項としてファイルの最後に書き込みます。次に、A[k]--> B[k] の最初の 1 つに対応する「ノード到着」である新しい値を「valueB」に与えます。

        if(count==1){

    middle_value = valueB;
    valueB = B[k];    

次に、ファイルを楽しみにして、A [l] のようにする必要があるトライアドの最後の値 (l = k+1 ) の前に停止する場所から for を増やします --> A の最初の値 == B[ l]。私はカウンターを増やし、カウンターが2に達すると、プログラムは3つの値を出力する必要があります。それが私がelseを最後に置く理由です..)

     for(l=k+1;l<N;l++){

      new_value=A[l];     

      if(new_value==valueB && valueA==B[l]){

              count++;

             if(count==2){

    printf ("%d,%d,%d\n\n",valueA,middle_value,valueB);

            }else{

         count=1;       
              }  
            }
           }

        }else{

         count=0;
       }
      } 
     } 
    }
   fclose(fp);
   fclose(fq);
   return (0); 
  } 

しかし、それは私が望むようには機能しません。しかし、たとえば、次のような2つの新しいファイルを作成した場合

file1.dat = 1,1,1,2,3

file2.dat = 2,4,7,3,1

トライアド 1,2,3 がある場合、プログラムは動作します (3 行目に # define N 6 を入力する必要があります)。


私が考えている問題は、プログラムが最初のファイルを使用して、valueA = 1、valueB = 2 に関連付けられている場合、ファイル 1 の 2 の位置を再度検索することです (これが「中間値」になります)。それは新しい valueB = 3 を与えます。今度は file1 の 3 を検索しますが、見つかりません。したがって、file1 にある 2 番目の '2' で渡され、新しい valueB = 4 に渡され、すべてがうまくいくはずです。しかし、そうではありません。理由がわかりません

4

1 に答える 1

1

したがって、あなたの方法には多くの問題があります。おそらく最大の問題は、3 つのループがあることです。

for(i=0  ;i<N;i++){
for(k=i+1;k<N;k++){
for(l=k+1;l<N;l++){

そして、各ループは、他のループが終了するところから始まります。ただし、一般に、ループを見つけるために、より小さなノードを調べる必要がある場合があります。たとえば、次のグラフがあるとします。

1 2 3
3 1 2

アプローチが機能しないことを確認できます。したがって、ループの範囲を拡張する必要があることがすぐにわかります。

また、多くの変数が浮かんでいます。場合によっては (常にではありませんが)、これはプログラムが不必要に複雑であることを示しています。多くの場合、かなり複雑な問題は、中間変数が多くなくても解決できます。

あなたのxandy変数は、単純な中間体として使用していたため、明らかに不要だったので、それらをカットしました。

2 つのファイル ポインター変数を使用しましたが、実際には 1 つしか必要ありませんでした。2枚目を切り出しました。

また、fcloseステートメントをファイル内で読む場所の近くに移動しました。これにより、ファイルを読むための丁寧な方法である、可能な限り短い時間でステートメントを開くことができます。

あなたのvalueAvalueB、およびcount変数はすぐに疑わしいと思いました。特にこのビット:

valueA=0;
valueB=0;     

valueA=A[i];
valueB=B[i];

それらに値を与え、すぐに値を変更します。

しかし、コードを詳しく見てみると、 と を使用valueAして、どちらを見ているかvalueBを追跡していることがわかります。そして、ループの深さを追跡するために使用します。しかし、これらのそれぞれは、コードの構造に固有のものです!ABcount

そこで、上で説明したように、すべてを切り取り、ループ範囲を広げた結果、次のようになりました。

#include <stdio.h>
#include <stdlib.h>
#define N 9

int main () {
  int A[N], B[N];
  FILE *fp;

  if ((fp = fopen ("file1.dat", "r")) == NULL) {
    printf ("Error opening file 1\n");
    exit (EXIT_FAILURE);
  }
  for (i = 0; i < N; i++)
    fscanf (fp, "%d", &A[i]);
  fclose (fp);

  if ((fp = fopen ("file2.dat", "r")) == NULL) {
    printf ("Error opening file 2\n");
    exit (EXIT_FAILURE);
  }
  for (i = 0; i < N; i++)
    fscanf (fp, "%d", &B[i]);
  fclose (fp);

  for(int i=0; i<N; i++)
    for(int j=0; j<N; j++)
      for(int k=0; k<N; k++)
        if(B[i]==A[j] && B[j]==A[k] && B[k]==A[i])
          printf("%d,%d,%d\n",A[i],A[j],A[k]);

  return 0;
}

残念なことに、各トライアド ループが 3 回検出されますが、すべてのループが検出されます。ループを 1 回検出する、またはループをより効率的に検出する、もう少し複雑なアルゴリズムがありますが、このアルゴリズムは元のコードに最も近いため、現在最も役立つ可能性があります。

于 2013-01-08T11:33:02.097 に答える