構造体配列の安定なソート

このQ&Aのポイント
  • C言語で構造体配列を安定なソートする方法を知りたいです。
  • バブルソートではなく、構造体の中の一つの要素をキーにしたソート方法を教えてください。
  • ソート対象はint型の要素のみで、上限は100程度なので、速度的な問題は考慮しなくても大丈夫です。
回答を見る
  • ベストアンサー

構造体配列の安定なソート

出席番号と得点の配列を持つ構造体配列で、 出席番号順に並んだ状態でqsortを使って得点をソートする場合、 同じ得点の人でも、出席番号順はばらばらになってしまいますよね。 調べてみて、バブルソートなど安定なソートを使えばいいということが分かったのですが、 qsortは標準ライブラリにあって、 比較関数も見よう見まねで作ってなんとかなったのですが、 他の方法となると具体的にどうすればいいのか、 よくわからない状況です。 http://homepage1.nifty.com/daccho/program/algo/sort3.htm こちらのサイトのソースファイルを見て、 普通のint配列のバブルソートは出来たのですが、 構造体配列を、構造体の中の一つの要素をキーにバブルソートできるようにするには、 ここからどのように変更すればいいのでしょうか? 並び替える内容はint型だけなので、文字列をソートできるようにする必要はなく、 ソート対象も少ないので(上限100程度)、速度的な問題は考慮しなくて大丈夫だと思います。 Cは勉強中で、基本文法がわかるぐらいという状況で、 もしかしたら変なことを言っているのかもしれませんが、 よろしくお願いします。

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

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.4

>構造体のメンバを引数に渡すにはどうすればいいかとか、 >bubble_sort(&table[0].score, 10); bubble_sort(&table[0], 10) とすればいいと思います。 >メンバの配列を比較してメンバの順番だけ入れ替えたら、 >名前と得点の対応が壊れるから、 構造体自体は、出席番号と得点を保持しているのだから、 出席番号から名前が引き出せるのであれば、対応をとる必要はないと思うのですが、構造体の配列の並びがどっか別にある名前テーブル(配列?)と対応しているということであれば、名前テーブルも並び替える必要があるのかなぁとか思いますが、そんな必要はないような気がします。 なんか、どういうデータ構造になっているかよくわからないので、勘違いしてたらすみませんです。 できたら、バブルソート版のプログラムを補足していただけますか?

penkoko
質問者

お礼

アドバイスが役に立ちなんとかできました。 ありがとうございました。 void swap(struct scoretable *ptr1, struct scoretable *ptr2) { struct scoretable w; w = *ptr1; *ptr1 = *ptr2; *ptr2 = w; } void bubble_sort(struct scoretable *ptr, int n) { int i, j; for(i=0; i<n-1; i++) { for(j=n-1; j>i; j--) { if(ptr[j-1].score > ptr[j].score) { swap(&ptr[j-1], &ptr[j]); } } } }

penkoko
質問者

補足

ありがとうございます。 >bubble_sort(&table[0], 10) >とすればいいと思います。 渡すのは構造体で、関数内でメンバにアクセスするということですか。qsortでもそうでした。 これだと関数を書き換えないと駄目ですよね。 バブルソート版のプログラムは、 http://homepage1.nifty.com/daccho/program/algo/sort3.htm です。 void swap(int *ptr1, int *ptr2) { int w; w = *ptr1; *ptr1 = *ptr2; *ptr2 = w; } void bubble_sort(struct scoretable *ptr, int n) { int i, j; for(i=0; i<n-1; i++){ for(j=n-1; j>i; j--){ if(*((ptr->score)+j-1) > *((ptr->score)+j)){ swap(((ptr->score)+j-1), ((ptr->score)+j)); } } } } bubble_sort()の引数の型を書き換えて、 メンバにアロー演算子でアクセスするようにしただけで、 間接指定演算子 (*) の使い方が不正です。 'swap' : 1 番目の引数を 'int' から 'int *' に変換できません。 などのエラーが出ています。 ポインタを理解していない状態なので、多分今は理解しようとしても理解できないと思います。 それは後で本を読んで勉強するとして、 とりあえず今は動くようになればいいのですが。 構造体は普通の構造体で、メンバとして出席番号と得点があるで 問題ないです。対応が壊れるというのは、構造体の仕組みを勘違いしていました。

その他の回答 (3)

  • moritan2
  • ベストアンサー率25% (168/670)
回答No.3

単純ミスじゃないでしょうか? if((u->score - u->score)!=0) これは if((u->score - v->score)!=0) でしょう?

penkoko
質問者

お礼

そこは間違いでした。 ありがとうございます。 ただやはりこの方法だとできないみたいです。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.2

>int配列のバブルソートは出来た のであれば、 比較する値を構造体のメンバの得点にして、 交換するのを構造体(値型だから)にするか、それぞれの、メンバを交換すればいいだけです。

penkoko
質問者

補足

すいませんが、 具体的にどのように変更すればいいのかが わからない状態です。 構造体のメンバを引数に渡すにはどうすればいいかとか、 bubble_sort(&table[0].score, 10); 配列の先頭要素を渡すということはこういうことなのか、それともこうなのか。 bubble_sort(&table[i].score, 10); 関数側のほうにも修正が必要なのかとか。 メンバの配列を比較してメンバの順番だけ入れ替えたら、 名前と得点の対応が壊れるから、 そうすると、最初に構造体のメンバだけでなく、 構造体配列そのものも渡して、関数の中でどうにかするということなんでしょうか。 そうするとやはり元の関数自体も変更する必要がありますよね。

  • a-saitoh
  • ベストアンサー率30% (524/1722)
回答No.1

比較関数を,「得点を比較するが,得点が同じで場合は出席番号で代償をきめる」というものにすれば,クイックソートでも大丈夫では?

penkoko
質問者

補足

ありがとうございます。 元々の、比較関数は int _cdecl cmp(const void *a, const void *b) { struct scoretable *u, *v; u = (struct scoretable *)a; v = (struct scoretable *)b; return u->score - v->score; } のようになってるんですが、これを、 int _cdecl cmp(const void *a, const void *b) { struct scoretable *u, *v; u = (struct scoretable *)a; v = (struct scoretable *)b; if((u->score - u->score)!=0) { return u->score - v->score; } else { return u->no - v->no; } } のようにかえたのでは駄目でした。 多分これでは間違いなのだと思うのですが、 具体的にどのように変えればいいのでしょうか。

関連するQ&A

  • qsortを用いた構造体配列のソート

    お世話になります。 http://simd.jugem.jp/?eid=116 を参考にqsortを用いた構造体配列のソートをC言語で記述しようとしています。 上記のページは、構造体のメンバが配列でない場合です 今回は、メンバが配列のときの構造体配列のソートを実現したいと思っています。 つまり、 typedef struct{ int a; int b[1024]; int c[1024]; }TEST; という構造体配列があって、 TEST base[256]; と宣言し、メンバの配列の添え字を基準としてソートしたいときには、どのようにqsortを用いれば良いのでしょうか、ということです。 どうしたらよいかわからず途方にくれています。 つまり、下のようなソートが行われるには、どのようなプログラムを書けばいいかということです。 構造体でソートするものとします。 構造体でソートできれば、qsortを使っていなくても構いません。 プログラムの得意な方がおりましたら、ご教授下さい。 <ソート前> //************************************************ test[ 0].b[0] = 3; test[ 1].b[0] = 102; ... test[255].b[0] = 1; ------------ test[ 0].b[1] = 99; test[ 1].b[1] = 200; ... test[255].b[1] = 2; ------------ ... ------------ test[ 0].b[1023] = 99; test[ 1].b[1023] = 9; ... test[255].b[1023] = 200; //************************************************** <ソート後>:test[x]ではなく、b[y]を基準としてそれぞれのくくりをソートしたい //************************************************ test[ 0].b[0] = 1; test[ 1].b[0] = 3; ... test[255].b[0] = 102; ------------ test[ 0].b[1] = 2; test[ 1].b[1] = 99; ... test[255].b[1] = 200; ------------ ... ------------ test[ 0].b[1023] = 9; test[ 1].b[1023] = 99; ... test[255].b[1023] = 200; **************************************************

  • 構造体のリストをソートしたい。

    ある名簿のリストを作りました。 以下のような構造体で、 typedef struct meibo{ char name[10]; int old; struct meibo *next; }MEIBO; これを、ポインタp->next->nameをたどっていって、名前が辞書順になるようにリストを作ったのですが、 これを年齢順にソートして表示させたいんです。 どんな方法があるんでしょうか? 一旦すべてを配列に格納して、クイックソート…とかも考えたのですが、すごく領域をとるし、なんか2度手間(最初から配列に順に格納していけばよかったなぁ・・・と。 それでもやっぱり最初から名列順にするときから配列に入れておくほうがいいのでしょうか? 教えてください。 (最初から年齢を比較してリストを作れば・・ってのはなしで、名列順のリストが存在するものとしてください。)

  • 構造体のソートの記述について

     C言語で自己参照構造体(beforeとnextで繋げてます)で名簿をつくり、年齢で昇順ソートをしようと考えています。  そこで、ソート関数の「qsort」というものを使ってソートしたいのですが、どのように使ったらいいのでしょうか?  参考例などがありましたら、教えていただけますか?  よろしくお願いします。

  • C言語の構造体にてバブルソートが上手くいきません‥

    C言語の構造体にてバブルソートが上手くいきません‥ 初めて質問致します。 以下は、構造体で、身長順にバブルソートを行うソース文ですが、 結果表示が、最下部に示したように、 5つのレコードのうち1つが消えてしまい、 残った4つのレコードのうちの1つが重複されて表示されてしまいます。 これが、なかなか解決できません‥。 既に結構調べており、また、早く解決できないといけないこともあり、 すみませんが、回答の形式でお願いできますと大変幸いです。 何卒よろしくお願い致します。 #include<stdio.h> #include<string.h> typedef struct kojin { char name[21]; int length; int weight; }KOJIN; int main(void) { int i, c, j; char buf[4]; KOJIN data[10]; KOJIN *d; printf(

  • 構造体配列のクイックソート

    こんにちわ。 構造体配列のリストを ポインタのつなぎ変えによるクイックソートで 以下のようなソートをしたいのですが、悩んでおります。 struct info { int count; struct info *prev; struct info *next; }; int main () { struct info info[5]; /* 初期値設定 */ quick_sort(info, 0, 5); return 0; } 上記のようにして、クイックソートをしたいのですが、 よくあるクイックソートだと 例えば初期値を <配列のindex>要素の値を <0> <1> <2> <3> <4> 5 1 4 3 2 などと定義した場合 普通のクイックソートだと <0> <1> <2> <3> <4> 1 2 3 4 5 というように並び変えられてしまい <配列のindex>と 要素の値の組み合わせが変わってしまいますが、 この組み合わせを変えず、 struct info *if; if = info; for (i=0; i<MAX; i++){ printf("%d", if->count); if = if->next; } printf("\n"); とすることで、indexとしては昇順になっていないが *nextをたどっていくことでちゃんと目的の値の昇順になっている というのを実現したいのですが、ポインタのつなぎ変えか何かが 間違っているようで うまいことできていません。 どなたかご教授いただけますでしょうか。 申し訳ありませんが、よろしウお願いいたします。

  • qsort/クイックソートについて

    構造体の配列をqsortで昇順に並び替えるプログラムを作成しています。 対象は数値項目で、単純にNo順に並び替えるイメージです。 クイックソートは、配列の内容によって処理時間が変わると聞いたので、一番遅くなる場合の時間を調べたいのですが、どのような並びだと一番遅くなるのでしょうか?

  • 構造体配列の並べ替え

    いつもお世話になっております。 VB6で構造体の配列をソートしたいと考えています。 具体的やりかたは調べたいと思うのですが、ヒントとしてひとつ教えてほしいことがありまして質問させていただきました。 たとえば 名前(string) 身長(integer) 体重(single) 何人分かを仮にprofileという名の構造体に入れて、普通の配列と同じ様に体重だけをソートしたとします。 すると体重だけがソートされてしまうのでしょうか? それとも構造体ごとソートされてくれるのでしょうか? 前者だとかなり悩むことになりそうなので、そこだけ教えていただきたく質問させていただきました。 よろしくお願いします。

  • 配列をソートさせたとき、もう一方の配列も同じようにソートさせたい

    タイトルが意味不明で申し訳ありません。 二つの配列があるとします。 片方には文字列、もう片方には数値が記録されているもので、最大添え字は同じです。 この数値の大きい順に並べ替えを行いたいのですが、 name[0]とcount[0] name[1]とcount[1] ・ ・ をペアで並べ替えたいのですが、その方法が分かりません。 sort関数を使うとどうしても片方のみしかソートできないし、バブルソートを用いて試みましたが、どうも並び替えられません。 連想配列を使う考えもありましたが、2つの配列をどうやって一つのハッシュに格納すればいいか分からず断念しました。 バブルソートの方にバグがあるのかもしれませんが、何か方法があればご教授いただけると幸いです。 よろしくお願いします。 バブルソート部分のソース(配列は@filelistと@countを使用) # ソート処理 for($i=0;$i<$#filelist;$i++){ for($j=0;$i<$j;$j++){ if($count[$i]<$count[$i+1]){ $tmp=$count[$i]; $count[$i]=$count[$i+1]; $count[$i+1]=$tmp; $tmp=$filelist[$i]; $filelist[$i]=$filelist[$i+1]; $filelist[$i+1]=$tmp; $k=$j; } $i=$k; } }

    • ベストアンサー
    • Perl
  • 構造体の配列について

    構造体配列を使った簡単なプログラムを組んでいるのですが、以下のソースコードをコンパイルし、実行したのですが、うまくいきません。 どなたかお力をお貸しください。 ・やりたい事 配列に以下のようにデータをscanf関数を使って入れたいです。 ----[0]---[1]---[2]--- [0] 1 | "あ" | "猫" | [1] 2 | "い" | "亀" | [2] 3 | "う" | "狐" | -登録する内容 番号、名前、好きなもの動物 ■ソース #include <stdio.h> struct hyou { int box[3][3]; }; int main(){ struct hyou *da; int i; for(i=0;i<2;i++){ printf("番号:\n");   scanf("%d",&da->box[i][0]); printf("名前:\n");   scanf("%s",&da->box[i][1]); printf("好きなもの:\n");   scanf("%s",&da->box[i][2]); } //テスト(2件表示) for(i=0;i<2){ printf("番号:\n"); printf("%d",a->box[i][0]); printf("名前:\n"); printf("%s",a->box[i][1]); printf("好きなもの:\n"); printf("%s",a->box[i][2]); } } //構造体配列の意味が違っていたらすみません。 以上、宜しくお願いします。

  • Javaには、構造体はないんですか?

     C言語の構造体みたいなのはないんですか? 野球のデータを扱っているのですが、構造体がないのでできません。 打率の順位をソートしたいのですが、Cでは構造体でソートすれば選手名まで全部ソートできたのですが。。。 Javaでは、いちいち選手名、打率などの配列を作っているのですが、打率をソートしてから選手名と一緒に表示しようとしても打率の配列だけ、ソートしてあり選手名の配列と打率の配列があいません。 要するに、打率の配列はソートし、選手の配列はデータを入力したときのままなので、順番が違っているのです。 うまい方法を教えてください。初歩的な質問でごめんなさい。

    • ベストアンサー
    • Java

専門家に質問してみよう