• ベストアンサー

ソートアルゴリズム(c言語)

この問題の番号の並び替えがどうしても分かりません。とき方を教えてください。 問題:nこの学生番号と音楽の点数からなる成績データを入力し、成績の順にデータを並び替えるプログラムを作りなさい。 入力             出力 10             ソート前データ 1 56           番号  音楽 2 47           1   56 3 85           2   47 4 57           3   85 5 96           4   57 6 75           5   96 7 81           6   75 8 31           7   81 9 50           8   31 10 76          9   50               10   76               ソート後データ               番号   音楽               5    96               3    85               7    81               10   76               6    75               ・    ・               ・    ・               (省略) 大変だとは思いますが、お願いします。

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

  • ベストアンサー
  • ymmasayan
  • ベストアンサー率30% (2593/8599)
回答No.5

No.4です。ミスがありました。すみません。 ご迷惑を掛けたNo.1さんにお詫びし訂正します。 >No.1の方の回答に補足します。 >i,jをループ用変数とし >i=0~n-1  nはデータ行数 >j=i+1~n これではうまくソートが出来ません。n-1はn-2のはずですね。これは基本選択法です。 バブルソート(隣接交換法)なら i=n-2~0,-1 j=0~i で (j) と (j+1) を比べて逆転を入れ替えます。

yamauchi
質問者

お礼

皆さんありがとうございました!自分で考えていたところ解答が分かりましたので報告しておきます。なお、ポイントは、特に一生懸命考えてくれたと思う方に方に差し上げようと思います。 <解答> #include<stdio.h> void main(void){ int d[100],c[100],n,a[100],i,j,x,y,max; printf("n:"); scanf("%d",&n); for(i=0;i<n;i++){ scanf("%d %d",&a[i],&d[i]); } printf("ソート前データ\n"); printf("番号 音楽\n"); for(i=0;i<n;i++) printf("%d %2d\n",a[i],d[i]); for(i=0;i<n-1;i++){ max=i; for(j=i+1;j<n;j++) if(d[max]<d[j]) {max=j; } x=d[i]; d[i]=d[max]; d[max]=x; y=a[i]; a[i]=a[max]; a[max]=y; } printf("\nソート後データ\n"); printf("番号 音楽\n"); for(i=0;i<n;i++){ printf("%2d %2d\n",a[i],d[i]); }}

その他の回答 (4)

  • ymmasayan
  • ベストアンサー率30% (2593/8599)
回答No.4

No.1の方の回答に補足します。 >i,jをループ用変数とし >i=0~n-1  nはデータ行数 >j=i+1~n これではうまくソートが出来ません。これはソートでなく総当りのループです。 正しくは i=n-1~0,-1 j=0~i で (j) と (j+1) を比べて逆転を入れ替えます。 これはバブルソート(隣接交換法)です。

  • ret
  • ベストアンサー率40% (8/20)
回答No.3

こんなのでどうでしょうか? #include <stdio.h> #include <stdlib.h> typedef struct{ int number; int result; }DATA; //qsort用比較関数 int int_cmp( const void* _data1, const void* _data2 ) { const DATA* cmp1 = (const DATA*)_data1; const DATA* cmp2 = (const DATA*)_data2; int sort; //両要素の差 sort = cmp2->result - cmp1->result; if(sort != 0) return sort; return cmp2->result - cmp1->result; } //main関数 int main(void){ DATA _data[10]; int i; char buf[256]; for(i = 0; i < 10; i++){ printf("学生番号を入力してください\n"); fgets(buf, 256, stdin); _data[i].number = atoi(buf); printf("成績を入力してください\n"); fgets(buf, 256, stdin); _data[i].result = atoi(buf); } //sort qsort( _data, sizeof(_data) / sizeof(DATA), sizeof(DATA), int_cmp ); for(i = 0; i < 10; i++){ printf("学生番号 = %d 成績 = %d\n", _data[i].number, _data[i].result); } (void)getchar(); return 0; } qsortを使っています。 検索エンジンでqsortとすると関数の詳細が出ますので、 解説はそれをご参考に…。 ただこれって構造体を扱うので、 10個程度なら問題ないのですが、 1万とか大きな数になると問題が大きいのですよね…(^^;。 構造体の交換に時間がかかってしまいますので…。 本当は各要素のポインタの配列をもう一つ用意して、 構造体ではなくそのポインタをソートすればいいのですが、 複雑になるのでやめました。 勉強をするなら、そちらも学ばれたほうが 後々役に立ちますよ(^0^)/

yamauchi
質問者

補足

わざわざ解答していただきありがとうございます.しかし、複雑過ぎてよく分かりません。僕の考えているプログラムを載せておきます。 include<stdio.h> void main(void){ int d[100],c[100],n,a[100],i,j,x,max; printf("n:"); scanf("%d",&n); for(i=0;i<n;i++){ scanf("%d %d",&a[i],&d[i]); } printf("ソート前データ\n"); printf("番号 音楽\n"); for(i=0;i<n;i++) printf("%d %2d\n",a[i],d[i]); for(i=0;i<n-1;i++){ max=i; for(j=i+1;j<n;j++) if(d[max]<d[j]) {max=j; } x=d[i]; d[i]=d[max]; d[max]=x; } printf("\nソート後データ\n"); printf("番号 音楽\n"); for(i=0;i<n;i++){ printf(" %2d\n",d[i]); } } このプログラムを少しだけ修正(番号の出力)すればうまくいくと思っています。すいませんが他の方もこのプログラムにあった解法をしてくれればうれしいのですが・・・。

回答No.2

調べる方針を書いてみますので参考にしてください。 まず、学生番号と点数を2次元配列に格納して扱います。 (ここでは配列名をAをします) A11=1(学生番号) A12=56(点数) A21=2 A22=47 A31=3 A32=85 …… そして、その二次元配列の一つ目の添え字(A21なら2の方の添え字) だけを考えて、ソートアルゴリズムを使用します。 アルゴリズムはバブルソートでもクイックソートでも ヒープソートでもかまいません。 (これはプログラミング関係の入門書をみれば どれかが載っています) 入れ替えのときに、学生番号の方の一つ目の添え字だけでなく、 点数の方の一つ目の添え字も入れ替えるのを忘れないように してやれば完成です。

  • paspas
  • ベストアンサー率52% (47/90)
回答No.1

ソートアルゴリズムもいろいろありますが、単純な物でよければ次のようにすればいかがでしょう。 データをd(n,2)に読み込みます。 d(n,0)が番号、d(n,1)が音楽の点数とします。 i,jをループ用変数とし i=0~n-1  nはデータ行数 j=i+1~n 比較式で d(i,1)とd(j,1)を比較しd(j,1)の方が大きければ d(i,1)とd(j,1),d(i,0)とd(j,0)をそれぞれ入れ替える。 ループが終われば順番に並んでいるはずです。

関連するQ&A

  • ソートアルゴリズム

    お忙しいところすいません。 先日授業で出された課題がどうしても分からなかったので教えていただきたいと思っています。 どうやってプログラムを作ればよいでしょうか。 問題は、 『N件の乱数データを用意し、昇順(または降順)に並べる。 データ件数、ソート所用時間を表示する。 ソート時間1~100秒で処理できるデータ件数を確認する。 ソートアルゴリズムは2種以上作成すること。』 です。

  • ソート処理について

    毎回お世話になっています。課題でソート処理が出題されたのですが、フローチャートすら書けない状況なので、どなたか力を貸していただけないでしょうか? 【処理概要】 個人成績表からレコードを取得し、取得したレコードを点数の高い順にソートし、順位・氏名・点数を個人成績表に出力する といったものです。 個人成績表は、氏名と点数の2項目で、レコード数は自由です。 とりあえず、私は10レコード作ったのですが、いろいろな個人成績表に対応できるように「レコード数は不明」の前提で、コーディんグするようにとのことです。 個人成績順意表は、「順位・氏名・点数」の順に出力とあり、 ソートの考え方として、【レコードを配列に取り込む→レコードを取り込む際に件数をカウントし、件数をn件とする】 とありました。 VBは全くの素人で、ソートに種類があることすら知らず、使い分けも知りませんでした。 どなたか力を貸していただけないでしょうか? 【自作個人成績表】 青木        076 井上        081 江藤        066 柏原        092 小林        087 斉藤        059 佐久間       076 関根        088 塚田        096 富田        083 となっています。 よろしくお願いいたします。

  • c++がわかりません。

    何らかの成績(テストの点数)をキー ボードから次々に入力する."-1"を入力 することで入力を終了させることにする. また,入力は最大100件までとする. • 入力が終了したら,点数の小さい順に(昇 順に)並べ替え(ソート)を行い,結果を 画面上に表示する. こちらの条件のプログラムどんな感じですか? ある程度はわかっていますが最初から教えていただけるとありがたいです。

  • C言語 ファイル処理を教えてください!

    089067 054086 090100  ・  ・ というように、あるテストでの英語と数学の点数が 上記のように入っているファイルを読み込み、 ・ファイル内のデータと入力した数値が一致すれば出力 ・ファイル内のデータと入力した数値と一致しなければ、【全てのデータを読み込んだ後にエラー文を1行出力】 というプログラムを作りたいのですが、 後者のエラー出力を設定がわかりません。 本を見たりサイトを調べたり、自分なりに色々してみたのですが、 どうしてもわからないので教えてください。 今作っているのが↓のプログラムですが、 やっぱり原因はwhileの設定かelseなんでしょうか・・・ while (fscanf(fp, "%3d%3d", &e_data, &m_data) == 2) { if ((e_data == n1) && (m_data == n2)) { printf("英語%03d 数学%03d\n", n1, n2); break; } else { printf("入力した点数の人はいません\n"); return(0); } }

  • ヒープソートは2重ソートできない?

     ソートに関して詳しい方、相談にのっていただけたらと思います。  CGIを使ってヒープソートするロジックを組みました。  そのルーチンはただ単項データをソートするだけでなく、たとえば、配列変数 n1 と 配列変数 n2 にそれぞれデータが入っていたとき、n1 をソートすると、それに連動して n2 の中身も一緒にソートされます。  言うならば、バラバラに並んだビデオテープを番号順に並べ替えると、一緒にタイトルも並べ変わる感じです。  ところが、配列 n1 をソートしていてたまに同じ数字が入っていることがあります。そういうときは n2 の順にしたいのです。  そこで、先に n2 をソートしてから n1 をソートするといいのではと考え、そのようにプログラムを組んでみました。  ところが実際には、n1 をソートした瞬間に、せっかく並べ替えた n2 の内容がバラバラになってしまうのです。  「n1 の内容が同じ場合は n2 を昇順に並べる」という処理を記述していても、実際には n2 の内容はバラバラです。  これはヒープソートを使用している限り仕方のないことなのでしょうか。あるいは何らかの解決方法を知っている方、よろしくお願いします。

  • C#でバブルソート

    テキストボックスに任意の整数を複数個入力し、ボタンを押すことで入力した数字を別のテキストボックスに昇順・降順表示するプログラムを作りたいと思っています。 例えば 入力用テキストボックスに1、10、5をキーボードで入力 ↓ 作っておいた「昇順に並び替え」のボタンをクリック ↓ 出力用テキストボックスに1、5、10と表示される (「降順に並び替え」のボタンをクリックした場合は、10、5、1と表示) といった感じです。 バブルソートを使って作りたいのですが、超初心者のため、数字同士の比較?や、テキストボックスへの出力の仕方が全く分かりません。 分かりにくい文章のみの状況説明になってしまいましたが、ご指導よろしくお願いします。 マイクロソフトのビジュアルのC#プロジェクトです。

  • ★C言語の問題です★

    C言語のプログラムの問題なんですが、どなたか以下の問題の1問でも解ける方がいればご回答おねがいします! または、アドバイスだけでもいいのでよろしくお願いします。 【問題】 1 西暦1868年から2007年までの年号を入力して和暦に変更して出力するプログ  ラムを作成するプログラム。  例 入力 1868  出力 明治元年       2007     平成19年 2 整数配列が-32768から32767の範囲の数しか扱えないとしたとき、10桁の整数同士  の足し算を行うプログラム。 3 3桁の整数の値を入力していき、-9999が入力されたところで、それまでに入力  された数の個数と合計を整数で、平均を浮動小数点数で出力するプログラム。 4 3つの文字列”Happy”と“New”と“Year”をつないで1つの文字列として出力する  プログラム。 5 学籍番号、氏名、出席からなる10人分のデータがある。出席の悪いものから並び替  えて表示するプログラム。  例  CA180002 山田太郎 70  CA170001 山田次郎 60  データは、適当なものを使います。

  • C言語をお願いします

    何が違うのか教えてください。 segmentation faultになります。 よく分からないので、プログラムを作っていただければ、助かります。 問 整数を入力し、降順並び変えてに表示。 ・入力した整数は配列に入れ、その配列を使って並び変える(入力終りの印は 1000 とする)。 ・入力する整数の個数は #define NUM 100 を使いなさい。 ・使うデータは、下記の例のように、キーボードから入力すること。 #include<stdio.h> #define NUM 100 int main(void){ int d[NUM]; int temp; int i,j,n; printf("Input scores.\n"); for(i=0; i<NUM && d[i]!=1000; i++){ scanf("%d",&d[i]); } n = i; for(i = 0; i < n; i++){ for(j = i + 1; j < n;j++){ if(d[j] > d[i]){ temp = d[i]; d[j] = d[i]; d[i] = temp; } } } printf("After sort."); for(i=0; i < n; i++){ printf("%d\n",d[i]); } return 0; } 実行例 Input scores. 60 30 45 90 100 0 1000 After sort. 100 90 60 45 30 0 よろしければ 問2 並び変えをする部分を mysort 関数にしたプログラムを作ってください。 main 関数から mysort 関数には点数の個数と sort 前の配列を渡し、並び変え結果の表示はmain 関数でお願いします。 (問題の意味が分かりません) 関数はさっぱり分かりません。 では、お願い致します。

  • C言語 入出力ファイルの読み書きとプリントアウト

    入力データ(番号、名前、年齢、住所)を入力データファイル「in.txt」から読み込み、番号順に並べ替えて、出力データファイル「out.csv」に書き出す&プリントアウトするプログラムを作りたいのですが、プログラムを実行する度にコンパイラからプリントアウトする方法(例えばプリンターをプログラム内で指定)を教えてください。回答お願いします

  • C++でのSORT

    受験番号(int型)と成績(int型)からなる表(可変長)を成績順に並び替えるsortを例えばSTLを使って実現したいと思います。 そこで、構造体をvectorコンテナにのせることを考えました。ですが、push_backの扱い方が間違っているようです。STLのSORTを使う知識以前に、複数要素を持つコンテナが作れません。 受験番号  成績 1     65 2     92 3     95 を 受験番号  成績 3     95 2     92 1     65 に並び替える。 #include <vector> #include <algorithm> struct goukakusya { int number; int score; }; main() { vector<goukakusya> table1; table1.number.push_back(1); table1.core.push_back(65); table1.number.push_back(2); table1.core.push_back(92); table1.number.push_back(3); table1.core.push_back(95); } よろしく、御願いします。