• 締切済み

二次配列のqsort

二次配列のqsortについて分かる方に教えて頂きたいのですが 一段落のプログラムを載らせていただきました.count3[j][i]をバブルソートで降順でやってみましたが高速が要求されるため,qsortを使ってやり直したいのですが (ちなみにcount1[j][i],count2[j][i]は前で定義してあります.count4[j][i]にはiの順番を記憶するための二次配列です)  ぜひともよろしくおねがいします. int ind_near_search(int j,int t) { int i,var_num,count3[IND][VAR],count4[IND][VAR],temp1,temp2,num=0,m=0; for(i=0;i<VAR;i++){ if(individual[j].x[i]==1){ //変数が1と0の場合分け count2[j][i]=t-count[j][i]; }else{ count2[j][i]=count[j][i]; } if(individual[j].x[i]==1){ //全てcount3に値を入れる count3[j][i]=count2[j][i]; }else{ count3[j][i]=count[j][i]; } } for(i=0;i<VAR;i++){ count4[j][i]=num++; } for(m=0;m<VAR-1;m++){ for(i=0;i<VAR;i++){ //バブルソートにより降順に並べ換え if(count3[j][i]<count3[j][i+1]){ temp1=count3[j][i]; count3[j][i]=count3[j][i+1]; count3[j][i+1]=temp1; temp2=count4[j][i]; //count4にはcount3の並べ替え後の対応する番号を入れる count4[j][i]=count4[j][i+1]; count4[j][i+1]=temp2; } } } for(i=0;i<VAR;i++){ var_num=count4[j][i]; //count4の大きい順番からその番号をvar_numに渡す if(individual[j].x[var_num]==0){//0と1の場合分け individual[j].x[var_num]=1; }else{ individual[j].x[var_num]=0; }

みんなの回答

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.3

>qsortにしたらどうやってcount4[j][i]は同じ機能を働かせるのか なんとなく判りました。 qsortは置換処理をqsort内でやっているので、 今回のような他の配列に対する入れ替えは出来ないでしょう。 クイックソートを自前で実装するかどうしてもqsortの 入れ替えその物を利用したいなら配列を別にするのではなく、 count3とcount4を構造体に纏めれば可能でしょう。 #include <stdio.h> #include <stdlib.h> struct hoge{  int cnt3;  int cnt4; }; //比較はcnt3で比較 int compare_int(const struct hoge *a, const struct hoge *b) {  return (a->cnt3 - b->cnt3); } int main( void ) {  int i,j;  struct hoge a[5][5] = {   {{ 1, 0 },{ 4, 1 },{ 2, 2 },{ 3, 3 },{ 5, 4 }},   {{ 21, 5 },{ 24, 6 },{ 22, 7 },{ 23, 8 },{ 25, 9 }},   {{ 31, 10 },{ 34, 11 },{ 32, 12 },{ 33, 13 },{ 35, 14 }},   {{ 51, 20 },{ 54, 21 },{ 52, 22 },{ 53, 23 },{ 55, 24 }},   {{ 41, 30 },{ 44, 31 },{ 42, 32 },{ 43, 33 },{ 45, 34 }},  };  for ( i = 0; i < 5; i++ ){   for ( j = 0; j < 5; j ++ ){    printf( "[%3d:%3d]", a[i][j].cnt3, a[i][j].cnt4 );   }   printf( "\n" );  }  printf( "\n" );  for (i = 0; i < 5; i++) {   qsort(a[i], 5, sizeof(struct hoge), (int (*)(const void*, const void*))compare_int);  }  for ( i = 0; i < 5; i++ ){   for ( j = 0; j < 5; j ++ ){    printf( "[%3d:%3d]", a[i][j].cnt3, a[i][j].cnt4 );   }   printf( "\n" );  }  printf( "\n" );  return 0; }

mars2608
質問者

お礼

aris-wizさん本当にありがとうございます. 大変参考になりました!! 早速やってみます.わからないところありましたらまた聞かせて下さい.助けました^-^.

mars2608
質問者

補足

度々申し訳ありませんが int compare_intは呼び出し関数の中ではどう宣言したらいいのでしょうか よろしくお願いします.例えば上記のint ind_near_search(int j,int t)の中ではどうすればいいのでしょうか

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.2

>上記のプログラムを例にして うーん、途中までしかない上に、このプログラムって qsortとあんまり関係ない気がしますが。。。 #include <stdio.h> #include <stdlib.h> int compare_int(const int *a, const int *b) { return *a - *b; } int main( void ) {  int i,j;  int a[5][10] = {   { 10, 15, 18, 11, 13, 19, 12, 17, 16, 14 },   { 2, 5, 6, 1, 4, 0, 7, 8, 9, 3 },   { 33, 34, 35, 37, 32, 30, 31, 38, 36, 39 },   { 22, 25, 23, 26, 21, 24, 20, 27, 28, 29 },   { 43, 44, 45, 47, 42, 40, 41, 48, 46, 49 },  };  for ( i = 0; i < 5; i++ ){   for ( j = 0; j < 10; j ++ ){    printf( "%3d", a[i][j] );   }   printf( "\n" );  }  printf( "\n" );  for (i = 0; i < 5; i++) {   qsort(a[i], 9, sizeof(int), (int (*)(const void*, const void*))compare_int);  }  for ( i = 0; i < 5; i++ ){   for ( j = 0; j < 10; j ++ ){    printf( "%3d", a[i][j] );   }   printf( "\n" );  }  printf( "\n" );  return 0; } これでも2次元配列のソートです。 こういうことではなくて?? 2次元配列をどのように並べ変えたいの?

mars2608
質問者

お礼

aris-wizさん レスありがとうございます.2次配列のqsortへの適用の参考になりましたが 実は上記のプログラムのcount3[j][i]はバブルソートでソートしていて、count3[j][i]ソートされた後のi個変数の順番を記憶するためのcount4[j][i]です.バブルソートだと上の書き方でソートしたあとでも対応するcount3[j][i]のiの番号はcount4[j][i]が記憶できるのですが qsortにしたらどうやってcount4[j][i]は同じ機能を働かせるのかわからなくて聞かせていただきました.

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.1

>qsortについて分かる方に教えて頂きたいのですが えっと、ご質問はなんでしょうか? qsortって標準ライブラリの関数ですが、 何がわからないのでしょうか?

mars2608
質問者

補足

すいませんが えっと,qsortはどうやって二次配列に適用するのでしょうか 宣言の仕方とかはわからないのですが 上記のプログラムを例にして教えていただければと思いますがよろしくおねがいします.

関連するQ&A

  • 二次配列のqsortですが

    Cの初心者ですがよろしくおねがいします。 二次配列をqsortでソートしたいのですがまだソートする前の順番も記憶したいのですがどうすればいいのでしょうか 分かる方にはぜひ教えていただきたいのです! 例えばcount[j][i]をqsortでソートし、昇順で並べ変えた後のiの元の順番に対して今の順番も記憶する場合でお願いします.

  • C言語のqsortについて

    現在、qsortのコードに取り組んでいます。 if (strcmp(ad, "ASC") == 0) { qsort(sin, sizeof(cnt), sizeof(sin[0]), cmp_u); } else { qsort(sin, sizeof(cnt), sizeof(sin[0]), cmp_d); } 恐らくこちらのqsortでの第二引数が書き方を間違えていると思うのですが、修正の方法が分からず、どなたか教えて頂けないでしょうか? #include <stdio.h> #include <time.h> #include <string.h> #include <stdlib.h> static char ad[10]; int cmp_u(const void* a, const void* d) { return strcmp((char*)a, (char*)d); } int cmp_d(const void* a, const void* d) { return strcmp((char*)d, (char*)a); } int main() { int num1, num2; char op; float answer; int r,i; FILE* fp; char c[11]; char sin[1000][1000]; char ad[8]; fp = fopen("log.txt", "a+"); if (fp == NULL) { printf("ファイルオープン失敗\n"); return -1; } while (1) { r = scanf("%d%c%d", &num1, &op, &num2); if (r != 3) { puts("input error"); return 1; } if (op == '+') { answer = num1 + num2; } else if (op == '-') { answer = num1 - num2; } else if (op == '*') { answer = num1 * num2; } else if (op == '/') { answer = (float)num1 / num2; } time_t t = time(NULL); struct tm* tm = localtime(&t); printf("%d/%02d/%02d ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); printf("%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); printf("%d%c%d,%f\n", num1, op, num2, answer); fprintf(fp, "%d/%02d/%02d ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); fprintf(fp, "%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); fprintf(fp, "%d%c%d,%f\n", num1, op, num2, answer); printf("計算を続けますか?"); scanf("%s\n", &c); if (strcmp(c, "no") == 0) { break ; } } fclose(fp); fp = fopen("log.txt", "r"); int cnt = 0; for (i = 0;i < 1000;i = i + 1) { if (fgets(sin[i], sizeof(sin[0]), fp)) ++cnt; else break; } fclose(fp); printf("ASC or DESC: "); scanf("%s", ad); if (strcmp(ad, "ASC") == 0) { qsort(sin, sizeof(cnt), sizeof(sin[0]), cmp_u); } else { qsort(sin, sizeof(cnt), sizeof(sin[0]), cmp_d); } for (i = 0;i < cnt;i = i + 1) { printf("%s", sin[i]); } return 0; }

  • 配列について

    以下の配列についての問題でわからないことがあるので、教えてください。 /* x と y の積を求める。 */ #include <stdio.h> int main(void) { int x[2][3] = {{1,2,3}, {4, 5, 6}}; int y[3][2] = {{1, 5}, {5, 3}, {8, 1}}; int ans[2][2] = {0}; int i, j, k, temp; for(i = 0; i < 2; i++) { for (k = 0; k < 2; k++) { temp = 0; for(j = 0; j < 3; j++) { temp += x[i][j] * y[j][k]; } ans[i][k] = temp; } } for(i = 0; i < 2; i++) { for(j = 0; j < 2; j++) { printf("%4d",ans[i][j]); } putchar('\n'); } return(0); } 以下の部分について詳しく説明してもらえないでしょうか? int ans[2][2] = {0};  int i, j, k, temp; for(i = 0; i < 2; i++) { for (k = 0; k < 2; k++) { temp = 0; for(j = 0; j < 3; j++) { temp += x[i][j] * y[j][k]; } ans[i][k] = temp; } }

  • 動的配列の受け渡しについて

    動的に定義した2次元配列を受け渡す方法がわからなくて困ってます。 配列に-1以外が入っている場合の行数を数えるプログラムを作成しています。 しかし、コンパイルすると下のエラーが出てコンパイルできません。 error:cannot convert 'long int **' to 'long int (*)[2] for argument '1' to 'long int count_line(long int (*)[2])' #include <stdio.h> long count_line(long arrau[][2]); int main(void){   long** test = new long* [100];   for(long num1=0 ; num1<100 ; num1++){     test[num1] = new long [2];   }   for(int i=0 ; i<100 ; i++){     test[i][0]=-1;     test[i][1]=-1;   }   for(int num2=0 ; num2<10 ; num2++){     test[num2][0]=1;     test[num2][1]=1;   }   int x=0;   x = count_line(test);   printf("x=%d\n",x); } long count_line(long array[][2]){   long count=0;   long end=0;   long roop=0;   while(end!=-1){     if(array[roop][1]!=-1){       count++;     }     end=array[roop][1];     roop++;   }   return(count); } どなたかお助けをー(T_T)

  • C言語を使って、ファイルの読み込みをして切り出して2次元配列に格納した

    C言語を使って、ファイルの読み込みをして切り出して2次元配列に格納したいのです。 1,2行目に配列の行の数と列の数が書かれ、3行目から改行とカンマ、スペースで区切られて配列が書かれているテキストを読み込んで2次元配列に格納する。 テキストの例) 4 3 1.1 1.2 1.3 1.4 1.5 2.1 2.2 2.3 2.4 2.5 3.1 3.2 3.3 4.4 3.5 というプログラムを書いています。色々と参考書やサイトを参考してとりあえずの形にはなったと思ったのですが、実行してもエラーが出ます。 どこまで動いているか調べたところ、一行ごとに読み出してそれを切り出して行くところでおかしな事をしてしまっているようですが、どう変えたらいいものか分かりません。 なので、その点のアドバイスと 大きさの分からないファイルから1,2行目を読み出すのはこれで変な動きをする恐れはないか の2点についてヒントでも構わないので、教えてください。 以下、書いたソースです(申し訳ないのですが、文字数の関係で一部省略しています。) #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[] ) { double ** mainhairetu; int size_x, size_y; /* size_x 行 size_y 列 */ int i,j,count=0,count2; int *cut,*temp2; double temp; char s2[] = " ,"; char gyou[10],*num; FILE *fil; while((fgets(gyou,10,fil)) !=NULL){ if(count == 0){ size_x=atoi(gyou); count++; }else if(count ==1){ size_y=atoi(gyou); count=count+1; }else{ break; } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ここでmallocを使ってcutとmainhairetuの2つの配列を作っています。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ count=0; for (i = 0; i < size_y+2; i++) { mainhairetu[i][0] = atof( strtok( fgets(cut,50,fil),s2 ) ); for (j = 1; j < size_x; j++){ if(count <=1){ count++; break; }else{ mainhairetu[i][j] = atof( strtok( NULL,s2 ) ); } } } for(i=0;i<size_y;i++){ for(j=0;j<size_y;j++){ printf("%f",mainhairetu[i][j]); } printf("\n"); } return(0); }

  • マージソート内の再帰処理にすいて

    #include<stdio.h> #define MAX 4 int temp[MAX]; void marge(int num[],int left,int right) { int i,j,mid,k   if(left>=right)return; mid=(left+right)/2; marge(num,left,mid);//(1) maege(num,mid+1,right);//(2) for(i=left;i<=mid;i++) temp[i]=num[i]; for(i=mid+1,j=right;i<=right;i++,j--) temp[i]=num]j]; i=left; j=right; for(k=left;k<=right;k++) if(temp[i]<=temp[j]) num[k]=temp[i++]; else num[k]=temp[j--] } マージソート内はこういった関数を記述してエラーもでないのですが、(1)と(2)の処理がよくわかりません。 (1)は再帰的に処理していってif(left>=right)return;の条件を満たした場合に(2)の処理に入っていきますよね? その場合、(2)の処理を行う際に(1)が(2)の再帰より前に記述されているので(1)がまた処理されるのでしょうか? 一連の流れを(1)、(2)を使って表してほしいです。

  • 配列のサイズを動的に拡張

    お世話になっております。 配列のサイズを動的に拡張について悩んでおります。例えばint x[5]という配列があって、データが埋まったら動的にx[6]にする・・ っといったものです。自分で試行錯誤した結果、以下のようなプログラムを作成しました。 int *data,count=0,num=10;// グローバル変数 // 配列にデータを加える関数add void add(int t){  if(count+1>num){ // サイズを超えたら配列をサイズを+1    int i,*tmp_data;    tmp_data = new int [count];    for(i=0;i<num;i++) tmp_data[i] = data[i]; // 一時的に保存    delete[] data; // 古いのを消す    data = new int [num+1]; // 新しく作る    for(i=0;i<num;i++) data[i] = tmp_data[i]; // 新しいのにコピー    num+=1; // 最大値をプラス    data[count]=t;    delete[] tmp_data;  }  else data[count]=t;  count++; // 入力されたカウントをプラス } main関数内で、data = new int [10];と宣言し、add(3);のように使用しています。またnewのメモリ確保のエラー処理は省いております。 動くことは動くのですが・・ご覧の通り、グローバル変数が3つになり、データをコピーしたりと、複雑になってしまいました。 もっと簡単に出来るのでは・・っと思い質問させて頂きました。 こうすれば、もっと簡単になるよ!など。。ご回答頂ければ幸いです。

  • 数独解答判定プログラム

    数独の解答判定プログラムを作成しているのですが、完成しません。下に僕の作ったプログラムを載せておくので間違い等の指摘をお願いします。 #include <stdio.h> #define row 9 #define column 9 int question[row][column]={ 915284376, 273916584, 468753912, 396178245, 742365891, 851492637, 629847153, 587631429, 134529768, }; int num; int singlenumber(void); int saferow(int, int); int safecolumn(int, int); int safebox(int, int, int); int main(void){ int judge; for(num = 1; num <= 9; num++){ int singlenumber(void); } if(judge == 0){ printf("おめでとう!! 正解です。"); }else{ printf("残念!! 不正解です。"); } return 0; } int singlenumber(void){ int i, j; int row_judge; int column_judge; int box_judge; int judge; for(i = 0; i < row; i++){ int saferow(int i, int num); } for(j = 0; j < column; j++){ int safecolumn(int j, int num); } for(i = 0; i < row; i++){ for(j = 0; j < column; j++){ int safebox(int i, int j, int num); } } if(row_judge == 0 && column_judge == 0 && box_judge == 0){ judge = 0; }else{ judge = 1; } return judge; } int saferow(int i, int num){ int k; int row_judge; for(k = 0; k < column; k++){ if(num == question[i][k]){ row_judge = 0; }else{ row_judge = 1; } } return row_judge; } int safecolumn(int j, int num){ int l; int column_judge; for(l = 0; l < row; l++){ if(num == question[l][j]){ column_judge = 0; }else{ column_judge = 1; } } return column_judge; } int safebox(int i, int j, int num){ int m, n; int box_judge01, box_judge02, box_judge03; int box_judge11, box_judge12, box_judge13; int box_judge21, box_judge22, box_judge23; int box_judge0, box_judge1, box_judge2, box_judge; for(m = 0; m < row ; m++){ if(m / 3 == 0){ for(n = 0; n < 3; n++){ if(num == question[m][n]){ box_judge01 = 0; }else{ box_judge01 = 1; } } for(n = 3; n < 6; n++){ if(num == question[m][n]){ box_judge02 = 0; }else{ box_judge02 = 1; } } for(n = 6; n < 9; n++){ if(num == question[m][n]){ box_judge03 = 0; }else{ box_judge03 = 1; } } } if(box_judge01 == 0 && box_judge02 == 0 && box_judge03 == 0){ box_judge0 = 0; }else{ box_judge0 = 1; } if(m / 3 == 1){ for(n = 0; n < 3; n++){ if(num == question[m][n]){ box_judge11 = 0; }else{ box_judge11 = 1; } } for(n = 3; n < 6; n++){ if(num == question[m][n]){ box_judge12 = 0; }else{ box_judge12 = 1; } } for(n = 6; n < 9; n++){ if(num == question[m][n]){ box_judge13 = 0; }else{ box_judge13 = 1; } } } if(box_judge11 == 0 && box_judge12 == 0 && box_judge13 == 0){ box_judge1 = 0; }else{ box_judge1 = 1; } if(m / 3 == 2){ for(n = 0; n < 3; n++){ if(num == question[m][n]){ box_judge21 = 0; }else{ box_judge21 = 1; } } for(n = 3; n < 6; n++){ if(num == question[m][n]){ box_judge22 = 0; }else{ box_judge22 = 1; } } for(n = 6; n < 9; n++){ if(num == question[m][n]){ box_judge23 = 0; }else{ box_judge23 = 1; } } } if(box_judge21 == 0 && box_judge22 == 0 && box_judge23 == 0){ box_judge2 = 0; }else{ box_judge2 = 1; } if(box_judge0 == 0 && box_judge1 == 0 && box_judge2 == 0){ box_judge = 0; }else{ box_judge = 1; } } return box_judge; }

  • クイックソートのプログラムについて

    一から自分なりにやってみましたが、再帰処理の部分がうまくゆきません。 改善方法をご教授願えたらと思います。 #include<stdio.h>   void qsort (int x[], int a, int b) {  int temp, kijyun, i;  kijyun = a;  i = a + 1;  while (i <= b)   {    if (x[i] < x[kijyun])     {      change (x, kijyun, i);      kijyun = kijyun + 1;     }    i++;   }  if (kijyun != 0) //基準より左側をソートする。   {    qsort (x, 0, kijyun - 1);   } //以下if文の部分で、うまくいきません。  if (kijyun != 9) //基準より右側をソートする。   {    qsort (x, kijyun + 1, 9);   } } int change (int x[], int a, int b) //x[b]をx[a]の位置に挿入させる。 {  int i, temp;  i = b;  while (i != a)   {    temp = x[i];    x[i] = x[i - 1];    x[i - 1] = temp;    i--;   } } int main (void) {  int i, x[9] = { 6, 8, 9, 5, 3, 2, 1, 4, 7 };  qsort (x, 0, 8);  for (i = 0; i != 9; i++)   {    printf ("\n%d", x[i]);   } }

  • qsortについて

    『独習C』を使って勉強しているのですがqsortの部分で *(int*)i - *(int*)j という文が出てくるのですが、この意味がよく分かりません ##演算子の使い方も分からないので、どなたか分かる方 回答お願いします。

専門家に質問してみよう