主キーソート(キーの優先順位をつけてソート)

このQ&Aのポイント
  • 主キーソート(キーの優先順位をつけてソート)について解説します。
  • 特定のキーを基準にして昇順にデータをソートする方法について説明します。
  • 複数のキーがある場合、優先順位をつけてデータをソートする方法について詳しく解説します。
回答を見る
  • ベストアンサー

主キーソート(キーの優先順位をつけてソート)

時刻から生成した乱数を、構造体「TEST」のメンバ変数 a, b, c に代入し、 メンバb を基準にして、昇順にクイックソートしてみます。 #include <stdio.h> #include <stdlib.h> #include <time.h> typedef struct{ int a; int b; int c; }TEST; int comp( const void *c1, const void *c2 ); int main(void) { int i; TEST base[10]; /* 乱数の生成 */ srand( (unsigned int)time( NULL ) ); for( i=0; i<10; i++ ){ base[i].a = rand() % 100; /* 0~99の乱数 */ base[i].b = rand() % 100; base[i].c = rand() % 100; printf( "%d¥t", base[i].a ); printf( "%d¥t", base[i].b ); printf( "%d¥t", base[i].c ); printf( "¥n" ); } /* TEST構造体のbを基準にソート */ printf( "¥n--TEST構造体のbを基準にソート--¥n¥n" ); qsort( base, 10, sizeof(TEST), comp ); /* ソート後のデータを表示 */ for( i=0; i<10; i++ ){ printf( "%d¥t", base[i].a ); printf( "%d¥t", base[i].b ); printf( "%d¥t", base[i].c ); printf( "¥n" ); } return 0; } /* 比較関数 */ int comp( const void *c1, const void *c2 ) { TEST test1 = *(TEST *)c1; TEST test2 = *(TEST *)c2; int tmp1 = test1.b; /* b を基準とする */ int tmp2 = test2.b; return tmp1 - tmp2; } ランダム結果 13 22 21 63 21 45 52 45 81 75 67 94 7 1 44 81 66 38 35 24 35 62 6 4 76 12 84 86 77 71 --TEST構造体のbを基準にソート-- 7 1 44 62 6 4 76 12 84 63 21 45 13 22 21 35 24 35 52 45 81 81 66 38 75 67 94 86 77 71 と、このように表示されます。 下段の真ん中の列を見ると、メンバ変数 b で並び替えられている事が分かります。 比較関数comp内では、TEST構造体でキャストしてから、bを取り出しています。 また、戻り値に「tmp1 - tmp2」を使うことで、 「a < b :負の値、a == b :0、 a > b :正の値」という条件に当てはめています。 とhttp://simd.jugem.jp/?eid=116で書かれていますが これはb列を基準にしたソートであり、a列とc列の優先順位は書かれていません キーの優先順位をb>a>cにするにはどうしたらよいでしょうか。 もっとたくさんキーあった時(a>b>c>d>e>f>g・・・)のようにキーの優先順位つけて昇順or降順にデータをソートしたいです。 よろしくお願いします

noname#237746
noname#237746

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

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8516/19358)
回答No.3

>キーの優先順位をb>a>cにするにはどうしたらよいでしょうか。 int tmp1 = test1.b; /* b を基準とする */ int tmp2 = test2.b; return tmp1 - tmp2; を int tmp1 = test1.b; /* b を基準とする */ int tmp2 = test2.b; if (tmp1 != tmp1) return tmp1 - tmp2; /* bが不一致なら、その結果を返す */ tmp1 = test1.a; /* bが等しい場合のみ、次に a を基準とする */ tmp2 = test2.a; if (tmp1 != tmp1) return tmp1 - tmp2; /* aが不一致なら、その結果を返す */ tmp1 = test1.c; /* bもaも等しい場合のみ、次に c を基準とする */ tmp2 = test2.c; return tmp1 - tmp2; に変えれば良いです。 d、e、f…と増やしたければ、同じように「優先するキーが不一致なら不一致と返し、一致した場合は次に優先するキーを比較」というのを、優先順位に合わせて繰り返しましょう。

noname#237746
質問者

お礼

なるほどです。なんかもやもやが取れてすっきりです。ありがとうございました。

その他の回答 (2)

回答No.2

> これはb列を基準にしたソートであり、a列とc列の優先順位は書かれていません 確かにb列を基準にしたソートになっていますが、この例ではb列だけでソートできてしまうので、a列とc列の優先順位は無関係です。b列以外の優先順位が問題になるのはb列が同じ値である場合です。 このことを踏まえれば、 > キーの優先順位をb>a>cにするにはどうしたらよいでしょうか。 比較関数でb列が一致したとき、つまりtmp1 - tmp2の値が0のとき、a列の値を比べ、それが一致しているときにc列の値を比べればよいことがわかるはずです。 キーがたくさんある場合、優先度の高いものから比較して、大小の判定がつけば、判定結果を返し、大小判定がつかないとき(値が一致しているとき)に次の優先度について判定を行う。キーの大小判定がつくまでこの操作を繰り返せばいいです。

noname#237746
質問者

お礼

そういうことだったですね、納得です。ありがとうございました。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

そ~いう比較関数を作ってください. あ, ちなみにだけど, このプログラムで「クイックソート」するかどうかは分からんよ.

関連するQ&A

  • クイックソート

    #include<stdio.h> #include<stdlib.h> #define MAX 10 int comp(const void *i,const void *j); int main(void) { int sort[MAX], i ; for(i=0 ; i<MAX ; i++){ sort[i] = rand(); } qsort(sort, MAX, sizeof(int), comp); for( i=0; i<MAX ; i++) printf("%d\n", sort[i]); return 0; } int comp (const void *i, const void *j) { return *(int*)i - *(int*)j; } これはクイックソートのプログラムなのですが、 int comp (const void *i, const void *j) { return *(int*)i - *(int*)j; } この部分がわかりません。ここでソートしているのですか?

  • C言語の参照はずしについて

    ソートのプログラムなんですが #include <stdio.h> #include <stdlib.h> int comp(const void *, const void *); int main() { int i; int test[6] = {10, 8, 2, 6, 4, 0}; qsort(test, (size_t)6, sizeof(int), comp); printf("\n"); for (i = 0; i < 6; i++) printf("%d\n", test[i]); return 0; } int comp(const void *a, const void *b) { static int i = 1; printf("%02d--%d,%d\n", i, *(int *)a, *(int *)b); i++; return (*(int *)a - *(int *)b); } 最後のreturnの()の中身がよくわかりません。「参照はずし」という事をしてるらしいんですが「参照はずし」とは何ですか意味も教えてください。

  • マージソートについて。

    マージソートについて勉強しており、プログラムを作ってみたのですが どうしてもcc=~~の箇所の数値がおかしく表示されてしまいます #include<stdio.h> int main(void) { int a[5]={20,40,15,35,50}; int b[3]={55,20,65}; int c[8]; int i,z,k; printf("a="); for(i=0;i<5;i++) { printf("%d ",a[i]); } printf("\nb="); for(z=0;z<3;z++) { printf("%d ",b[z]); } while(i <= 5 && z <= 3){ if(i < z){ a[i]=c[k]; i++; } else if(i > z){ b[z]=c[k]; z++; } } while(i<5 && z<3) { i=k; i++; z=k; z++; } printf("\nc=") ; for(k=0;k<8;k++) { printf("%d ",c[k]); } return 0; } ご教授していただければ幸いです。

  • c言語 select sort

    最大値検索法のプログラムコードです。 どこがおかしいのでしょうか? 分かる方、教えてください。 よろしくおねがいします。 swapのプログラムコード #include <stdio.h> void swap(int *px,int *py); int main (void) { FILE *fp; if ((fp=fopen("file.txt","rt"))==NULL){ printf("File open error.\n"); return 0; } int i,a[100]; for(i=0;i<100;i++){ fscanf(fp,"%d,",&a[i]); //ファイルから読み込み処理。// } fclose(fp); for(i=0;i<10;i++) printf("[%d]=%d\n",i,a[i]); /*1.ソートすべきデータの中で最大のデータを見つけ、 2.そのデータを最後のデータと入れ替える。 最大データは配列のどこにあるのか⇒maxi              その値⇒max とする。*/ //データが10個の場合 int max,maxi,j; max=a[0],maxi=0; for(i = 0;i < 9; i++){ if(a[i + 1] > max){ max = a[i + 1]; maxi = i + 1; } swap(&a[maxi],&a[9-j]); /* コマンド $cc sort.c swap.c */ for(j=0;j<9;j++){ printf("%d\n",j); max=a[0], maxi=0; for(i=0;i<9-j;i++){ //最大値をもつデータ探索;(カウンタ変数) max++; } //最大データと探索範囲最後のデータとの入れ替え: //void swap(int *px, int *py){ int n,*px,*py; n = *px; *px = *py; *py = n; // } if((fp=fopen("file.txt","wt"))==NULL){ printf("File open error.\n"); return 0; } for(i=0;i<100;i++){ fprintf(fp,"%d",a[i]); } fclose(fp); } } sort.cのプログラムコード #include<stdio.h> void swap (int *px,int *py); int main(void) { int a[0],b,maxi,j,max; max=a[0],maxi=0; printf("input \"a\" as integer = "); scanf("%d",&a); printf("input \"b\" as integer = "); scanf("%d",&b); printf("Before swap...\n"); printf("a - b = %d, a / b = %d...%d\n",a-b,a-b,a-b); // swap(&px,&py); swap(&a[maxi],&a[9-j]); printf("After swap...\n"); printf("a - b = %d, a / b = %d...%d\n",a-b,a-b,a-b); return 0; } void swap (int *px,int *py) { int n; n = *px; *px = *py; *py = n; } 実行結果 /tmp/ccBGIpCi.o(.text+0x0): In function `main': : multiple definition of `main' /tmp/ccMCttJd.o(.text+0x0): first defined here /usr/bin/ld: Warning: size of symbol `main' changed from 304 in /tmp/ccMCttJd.o to 641 in /tmp/ccBGIpCi.o collect2: ld はステータス 1 で終了

  • ソートの名称について

    以下のようなソートに、選択ソートやバブルソート等といった名称は存在しますか? #include <stdio.h> int main(void) { int array[10]; int i, j, tmp; /* Input */ for(i=0; i<sizeof(array)/sizeof(int); i++){ printf("array[%d]> ", i); scanf("%d", &array[i]); } /* Sort */ for(i=0; i<sizeof(array)/sizeof(int)-1; i++){ for(j=i+1; j<sizeof(array)/sizeof(int); j++){ if(array[i]>array[j]){ tmp = array[i]; array[i] = array[j]; array[j] = tmp; } } } /* Output */ for(i=0; i<sizeof(array)/sizeof(int); i++){ printf("array[%d]: %d\n", i, array[i]); } return 0; }

  • クイックソート

    クイックソートのプログラムを作ったのですがうまくいきません 汗 コンパイル時に sample1.c: In function ‘quicksort’: sample1.c:31: error: expected expression before ‘]’ token sample1.c:32: error: expected expression before ‘]’ token sample1.c:32: error: too few arguments to function ‘quicksort’ とでます。 まだアルゴリズムやCは勉強始めたばかりで基本的なところでつまって いるかもしれません。ご教授おねがいします。 /*クイックソート*/ #include<stdio.h> #define MAXDATA 10 #define swap(type,a,b) {type m; m = a; a = b; b = m;} void quicksort(int a[],int left ,int right) { int i,j,pivot; pivot = a[left]; i = left + 1; j = right; while(i <= j){ while(a[i]<pivot) i++; while(a[j]>pivot) j--; if(i<j){ swap(int,a[i],a[j]); i++; j--; } } swap(int,a[left],a[j]); quicksort(a[],left,j-1); quicksort(a[],j+1,right); } int main(void) { int k,j,sort[MAXDATA]; for(k=0;k < MAXDATA;k++) {printf("sort[%d]:",k); scanf("%d",&sort[k]);} for(k=0;k < MAXDATA;k++) printf("%3d",sort[k]); puts("ソートしますか? Yes:1 No:0 ///"); scanf("%d",&j); if(j==1){ quicksort(sort,0,MAXDATA-1); for(k=0;k < MAXDATA;k++) printf("%3d",sort[k]); } putchar('\n'); return(0); }

  • java

    このプログラムをjavaでかくとどうなりますか? #include<stdio.h> #include<stdlib.h> #include<time.h> int comp(const void *a, const void *b){  return *(int*)a - *(int*)b; } int main(void){  int i;  int sep[9];  srand((unsigned int)time(NULL));  sep[0] = 0;  sep[8] = 100;  for(i=1;i<8;i++){   sep[i] = rand() % 101;  }  qsort(sep+1, 7, sizeof(int), comp);  for(i=0;i<8;i++){   printf("a[%d] = %d;\n", i, sep[i+1] - sep[i]);  }  return 0; }

    • ベストアンサー
    • Java
  • c言語の問題です。ファイルからデータを読み込み連結リストに記憶しソートするプログラムです。お願いします

    ソート部分がどうしてもできません。 またソートは以下のアルゴリズムで行うものです 与えられたリストをリストA、ソート済みのリストをリストBとする。処理の開始段階では、リストBは空である。 1.リストAの要素の中で、最大値をもつ要素Cを探す。 2.要素CをリストAから削除する。 3.要素CをリストBの先頭に挿入する。 4.リストAが空であれば終了。空でなければ 1. にもどる。 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct physical Physical; struct physical { char name[41]; int age; float height; float weight; Physical *next; }; void read_data(char *file,Physical *p,Physical *tail); int comp1(const Physical *, const Physical *); int comp2(const Physical *, const Physical *); int comp3(const Physical *, const Physical *); int comp4(const Physical *, const Physical *); void sort(char *arg,Physical *p,Physical *q); Physical *listsort(Physical *p, int (*compar)(const void *, const void *)); int main(void) { char s[20],t,u[20]; Physical *p,*tail,*q; p=malloc(sizeof(Physical)); q=malloc(sizeof(Physical)); tail=malloc(sizeof(Physical)); while(1) { printf("CMD>"); fflush(stdout); fgets(s,20,stdin); sscanf(s,"%c %s",&t,u); switch(t){ case 'q':exit(0); case 'r':read_data(u,p,tail); break; case 's':sort(u,p,q); break; case 'd': while(q!=NULL) { printf("%s %d %.1f %.1f ",q->name,q->age,q->height,q->weight ); q=q->next;} break; } } free(p); return 0; } void read_data(char *file,Physical *p,Physical *tail){ FILE *fp; char string[100]; Physical header; tail=&header; header.next = NULL; p->next = NULL; tail->next = p; tail = p; if ((fp = fopen(file, "r")) == NULL) { exit(1); } while(fgets(string,sizeof(string),fp)!= NULL) { sscanf(string,"%s %d %f %f",p->name,&p->age,&p->height,&p->weight); Physical *tail2; tail2=malloc(sizeof(Physical)); tail2->next=NULL; p->next=tail2; p=tail2; } fclose(fp); } void sort(char *arg,Physical *p,Physical *q){ if(strcmp(arg,"name") == 0) q=listsort(p,(int(*)(const void*, const void*))comp1); if(strcmp(arg,"age") == 0) q=listsort(p,(int(*)(const void*, const void*))comp2); if(strcmp(arg,"height") == 0) q=listsort(p,(int(*)(const void*, const void*))comp3); if(strcmp(arg,"weight") == 0) q=listsort(p,(int(*)(const void*, const void*))comp4); } Physical *listsort(Physical *p,int (*compar)(const void *, const void *)){ Physical *q, *max,*s,*head; s=malloc(sizeof(Physical)); head=malloc(sizeof(Physical)); head=NULL; while(p->next){max = p, q = p->next; while( q->next ) { if( compar(q->next,max->next) ) max = q; q = q->next;} s=max->next; max->next=max->next->next; if(head==NULL) {head=s;} s->next=s; } return head; } int comp1(const Physical *a, const Physical *b){ return (strncmp(a->name,b->name,sizeof(Physical))); } int comp2(const Physical *a, const Physical *b){ if(a->age > b->age) return 1; else return 0; } int comp3(const Physical *a, const Physical *b){ if(a->height > b->height) return 1; else return 0; } int comp4(const Physical *a, const Physical *b){ if(a->weight > b->weight) return 1; else return 0; }

  • C言語のソートについて

    C言語で下記のファイルの中身を昇順と降順で出力しようとしているのですが、ソートが上手くいっていない状況です。 どなたか修正点を教えて頂けないでしょうか? 「ファイルの中身」 2022/11/14 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/14 16:20:18 8+8,16.000000 2022/11/15 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/18 16:20:18 8+8,16.000000 2022/11/17 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/14 16:20:18 8+8,16.000000 「ソースコード」 #include <stdio.h> #include <string.h> #include <stdlib.h> int cmp_u(const void* a, const void* d) { return *(char*)a - *(char*)d; } int cmp_d(const void* a, const void* d) { return *(char*)d - *(char*)a; } int main() { int r,i,n; FILE* fp; char sin[9][1000]; fp = fopen("log.txt", "r"); if (fp == NULL) { printf("ファイルオープン失敗\n"); return -1; } for (i = 0; i < 9; i++) { fscanf(fp, "%s", &(sin[i])); } fclose(fp); printf("ASC or DESC: "); scanf(" %s", &ad); if (strcmp(ad, "ASC") == 0) { qsort(sin, 9, sizeof(char), cmp_u); } else { qsort(sin, 9, sizeof(char), cmp_d); } for (i = 0; i < 9; i++) { printf("%s\n", sin[i]); } return 0; }

  • ポインタを使ったソートプログラム

    #include<stdio.h> void swap(double *a,double *b) { double tmp; tmp=*a; *a=*b; *b=tmp; } void sort3d(double *pa,double *pb,double *pc) { if(*pa>*pb) { swap(pa,pb); } if(*pb>*pc) { swap(pb,pc); } if(*pa>*pc) { swap(pa,pc); } } int main(void) { double num1=3.14; double num2=2.97; double num3=0.01; sort3d(&num1,&num2,&num3); printf("d1の値=%.3d\n",num1); printf("d2の値=%.3d\n",num2); printf("d3の値=%.3d\n",num3); return 0; } ポインタを使ったソートプログラムを作ってみました。 ところが、コマンドプロンプトを使って動作させたら、 結果がうまく表示されませんでした。 どこがおかしいのか指摘していただけると嬉しいです。

専門家に質問してみよう