- ベストアンサー
配列・ポインタに関する問題について
この春IT系の会社に入社し、ただいまプログラミングの研修中の者です。 学生時代はプログラミングとは無縁の存在でしたので、プログラミングに関しては初心者です。 早速質問なのですが、 「(30点、47点、99点、64点…)などの50人分の生徒のテストの点数の上位・下位5名分を表示せよ。」 という問題に詰まってしまい困っています。 わからないのは以下の2点です。 (1)どうやって成績順に並べるのか? (2)成績順に並べた後、どうやって上位・下位5名を選出するのか? (1)に関してはソートを使うと思うのですが、配列とポインタがどう絡んでくるのかいまいちイメージがわきません。 また、プログラミングのサンプルソースも見たのですが void sort(const int num, int *ary)や sort(ARRAY_SIZE, array); の部分がよくわかりません。 ()があるということはifやforと同じような位置付けなのでしょうか。 (2)に関してはif文を使用して条件付け→選出でよいのでしょうか? 初心者丸出しの質問でお恥ずかしい限りですが、アドバイスお願いいたします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
★どうもソート部分も自分で実装するようですね。 ・全体的には回答者 No.2 さんのアドバイスを参考にして下さい。 私はソート部分のみをアドバイスします。 ・ソートのアルゴリズムはいろいろありますが、一番簡単なソートは『バブルソート』です。 このソート方法は、配列で隣り合う2つを比較してより大きい数を配列イメージで右側に 残す(入れ替える)事でソートを完了します。なおソートには『昇順』、『降順』の2タイプが あります。 『昇順』⇒小さい順に並べること 『降順』⇒大きい順に並べること ・今回は成績順に並べるようですが、一般に成績順とは、大きい順に並べることになるので ソート処理は『降順』タイプになります。実装すべきソート関数 sort は引数の並びから データ件数、データ配列の2つを受け取ります。 ソートの考え方: ・説明の都合上 4 人分の成績データを用意します。 そのデータとは、30点、47点、99点、64点です。→int array[ 4 ] = { 30, 47, 99, 64 }; ソート処理は降順タイプなので、左側から右にかけて大きい数→小さい数の並びになります。 ●1回目の比較スキャン (1)30点、47点を比較する。 左側を大きい数にするため、30点、47点を入れ替える。 int array[ 4 ] = { 47, 30, 99, 64 }; (2)次は30点、99点を比較する。 左側を大きい数にするため、30点、99点を入れ替える。 int array[ 4 ] = { 47, 99, 30, 64 }; (3)その次は30点、64点を比較する。 左側を大きい数にするため、30点、64点を入れ替える。 int array[ 4 ] = { 47, 99, 64, 30 }; (4)配列の最後なので1回目の比較スキャンは終了 ●2回目の比較スキャン (1)47点、99点を比較する。 左側を大きい数にするため、47点、99点を入れ替える。 int array[ 4 ] = { 99, 47, 64, 30 }; (2)次は47点、64点を比較する。 左側を大きい数にするため、47点、64点を入れ替える。 int array[ 4 ] = { 99, 64, 47, 30 }; (3)2回目はここで比較スキャンを終了します。 理由は、30点は1回目で一番小さい数であると確定しているため47点が2番目に小さい数と なるからです。 ●3回目の比較スキャン (1)99点、64点を比較する。 左側を大きい数にしますが、すでに99点が大きいので入れ替えません。 int array[ 4 ] = { 99, 64, 47, 30 }; (2)3回目はここで比較スキャンを終了します。 理由は、30点、47点が1回目、2回目で小さい数であると確定しているためです。 ●これで4つの成績が大きい順のソートされました。 大小比較した際に、配列要素を入れ替えるとき『添え字』を使って入れ替える場合があります。 しかし、配列要素のサイズが大きい場合は、ポインタを使っての入れ替えが高速になるため、 一般にはデータ内容を表したポインタの入れ替えを行います。配列とポインタを格納している 配列(ポインタ配列)を最初に理解して下さい。 ・http://ja.wikipedia.org/wiki/%E3%83%90%E3%83%96%E3%83%AB%E3%82%BD%E3%83%BC%E3%83%88→『バブルソート』 最後に: ・下の参考文献に、ほぼ答えのソースが載っていますが、コピー&ペーストするだけではなく、 仕組みもちゃんと理解してから使って下さい。バブルソート以外にもたくさんのソート方法が ありますので、時間に余裕があれば検索してみて下さい。 ・クイックソート、マージソート、挿入ソート、シェルソートなどなどあります。 http://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%BC%E3%83%88→『いろいろなソート』 ・バブルソートを高速にしたアルゴリズムとして、シェーカーソート、コムソートがあります。 参考文献: ・http://homepage3.nifty.com/mmgames/c_guide/a_sort-bubble.html→『バブルソート』 ・http://www.codereading.com/algo_and_ds/algo/bubble_sort.html→『バブルソート』 ・http://www.ics.kagoshima-u.ac.jp/~fuchida/edu/algorithm/sort-algorithm/bubble-sort.html→『バブルソート』
その他の回答 (2)
(1)どうやって成績順に並べるのか? ランダムに点数が入っている配列を int array[50]; とするならば、このdataの中身を降順で並び替えればいいと思います。 sort関数のプロトタイプを見た限りでは、 sort(50,array); で並び替えられると思います。 ただし、このsort関数は、昇順、降順の指定が無いのでどちらの方法で 並び替えられるのか解らないなぁ。 普通は大小比較する関数のポインタを引数に取るんだけど。 このsort関数はあなたの会社で用意されているオリジナルのソート関数なのかな? (2)成績順に並べた後、どうやって上位・下位5名を選出するのか? arrayの中身は降順(あるいは昇順)に並んでいるので、 配列の先頭から5つ分のデータと、最後から5つのデータを取得すればよいと思います。 void sort(const int num, int *ary) はプロトタイプ宣言と呼ばれる、sort関数のinput,outputの書式です。 戻り値は無し(void), 第一引数にソートしたい配列の要素数(int), 第二引数にソートすべきデータが入った配列の先頭アドレス です。 sort(ARRAY_SIZE, array); は実際にsort関数を実行している部分でしょう。 ARRAY_SIZEはソースのどこかで #define ARRAY_SIZE 50 と宣言してあると思います。50という数字を、人が見てわかりやすい文字列(ARRAY_SIZE)に置き換えています。 arrayは配列の先頭アドレスを示しています。
お礼
本当なら問題をきちんととき終えた時にお礼を書くのがよいのだと思いますが、今日の夜~明日いっぱいお礼ができませんので、本日お礼をさせていただきます。 ご指導いただいた内容は、正直よく理解できていないのですが(すみません)、おぼろげながら概要が見えてきました。今週の日曜にじっくりと勉強してアドバイスの内容を理解したいです。 >arrayの中身は降順(あるいは昇順)に並んでいるので、 >配列の先頭から5つ分のデータと、最後から5つのデータを取得すればよいと思います。 今まで「どんどんifやforを利用していくべき」という考えに凝り固まっていたせいで、そのような発想を思いつきませんでした。まだまだ問題数が足りませんね… このたびはどうもありがとうございました。
- nidoking
- ベストアンサー率69% (18/26)
研修中ということで、あまり詳しい回答は"研修"になりませんね・・ >void sort(const int num, int *ary)や sort(ARRAY_SIZE, array); 言語環境は、C++でしょうか? listクラスのsortメンバ関数を使うのが一般的と思われます。 詳しくは、C++のリファレンスを見ていただくのがよいと思いますが、 参考のURLをかいておきます。
お礼
補足にも書きました通り、言語環境が違うのでなんともいえないのですが、 参考URLのHPはCの解説も載っている上、大変わかりやすいですね! 配列のところから復習してみます。 ありがとうございました。
補足
うっかりして一番重要なことを書き忘れていました…。申し訳ありません。 言語はC++ではなく、Cです。
お礼
丁寧な解説とたくさんの参考文献、どうもありがとうございます。 バブルソートの考え方に関してはだいたい理解できたつもりです。 実際にそれをCで書くときに理解できていない関数が出てくると、 少し混乱してしまいそこで問題を解くのがストップする、といった状況です。 一度しっかりと復習してからもう一度解いてみるつもりです。 コピペは、たとえそれでうまく問題が解けても 結局はどうしてそれが正解なのかわからず混乱するのが目に見えていますし、意味がないのでいたしません。(あたりまえですが)