160 likes | 264 Views
第 1 回 Sun と Unix, 中央値. 情報科学科 井口幸洋 iguchi@cs.meiji.ac.jp. 本実習の目的. 情報科学科の学生としての必須条件 プログラミング言語の1つを確実に理解する必要あり 頭と体を実際に使って(実習して)習得するのが一番 これができれば他の言語もすぐに習得可能 実社会では卒業生も C, C++, JAVA , Perl, Visual BASIC, Assembly 言語 , etc. など様々な言語を短期間に理解し,開発しなければならない データ構造とアルゴリズム どれを選ぶかによって数倍~数千倍の性能差が生じる
E N D
第1回 SunとUnix, 中央値 情報科学科 井口幸洋 iguchi@cs.meiji.ac.jp ソフトウェア実習I
本実習の目的 • 情報科学科の学生としての必須条件 • プログラミング言語の1つを確実に理解する必要あり • 頭と体を実際に使って(実習して)習得するのが一番 • これができれば他の言語もすぐに習得可能 • 実社会では卒業生もC, C++, JAVA,Perl, Visual BASIC, Assembly言語, etc.など様々な言語を短期間に理解し,開発しなければならない • データ構造とアルゴリズム • どれを選ぶかによって数倍~数千倍の性能差が生じる • 多くのプログラムを実際に書いて動かすのが理解の早道 ソフトウェア実習I
目的 • しばらくぶりのプログラミングなので。。。。簡単なものを実習してみましょう. • クイックソートの応用 • 中央値を求めるプログラム ソフトウェア実習I
中央値(median)とは • n個のデータを大小順にソート(整列)したとき,その中央の位置にあるデータのこと • nが奇数の時: m = (n+1)/2,nが偶数の時: m = n/2 とするとm番目の大きさのデータ • 例 • 4 15 12 9 6 の中央値は? • ソート後: 4 6 9 12 15 • 中央値は 9 ソフトウェア実習I
中央値を求める方法 • 方法1:n個のデータをソートしてからm番目を取り出す. • ソート法としてはクイックソートが効率が良い. • 計算量は O(n log n). • 中央値だけを取り出すのに全体を並べるのは無駄! • 方法2: O(n) で求める方法を考える. ソフトウェア実習I
配列v [0] [1] [2] [3] [4] [5] [6] [7] 5 17 15 15 8 8 17 5 1 1 9 9 12 12 3 3 真ん中(3番目)をpivot(軸)にする (2) pivotを左端の値と交換 last =left =0 17 15 8 5 1 9 12 3 i=1 right=7 i=1,...,7まででpivotつまりv[left]よりも小さいものを左に集める. (3) 中央値を求める手続き:sort(int *v, int left, int right) sort(v, 0, 7); (1) ソフトウェア実習I
last =left =0 i=1 right=7 i=1,...,7まででpivotつまりv[left]よりも小さいものを左に集める. (3) swap(v, ++last, 1); last=1; i=2 17 15 8 5 1 9 12 3 17 15 8 5 1 9 12 3 (4) last=2; swap(v, 2, 2); 17 15 8 5 1 9 12 3 (5) swap(v, 3, 3); 中央値を求める手続き(2) ソフトウェア実習I
swap(v, 7, 7); swap(v, left, last); 最後の値とpivotを交換 (7) 3 15 8 5 1 9 12 17 last=7; 何がわかったか? pivotが入ったのが配列v[7]. v[0]~v[6]はこれより小さい.7>=3だから v[0]~v[6]の どれかに中央値はあるはず! 中央値を求める手続き(3) この場合,他のすべてがpivotより小さいことに注意 途中を省略。。。。 last=7; 17 15 8 5 1 9 12 3 (6) ソフトウェア実習I
配列v [0] [1] [2] [3] [4] [5] [6] [7] 真ん中(3番目)をpivot(軸)にする 中央値を求める手続き(4) ここは考えなくて良い sort(v, 0, 6); (8) 3 15 8 5 1 9 12 17 (9) pivotを左端の値と交換 5 15 8 3 1 9 12 17 last =left =0 i=1 right=6 i=1,...,6まででpivotつまりv[left]よりも小さいものを左に集める. (10) 5 15 8 3 1 9 12 17 ソフトウェア実習I
中央値を求める手続き(5) last =left =0 i=1 right=6 i=1,...,6まででpivotつまりv[left]よりも小さいものを左に集める. (10) 5 15 8 3 1 9 12 17 i=2 last=0 right=6 (11) 5 15 8 3 1 9 12 17 ソフトウェア実習I
5 3 1 15 8 9 12 17 i=4 last=1 right=6 (13) 5 3 8 15 1 9 12 17 pivotより小さいのでlast++と交換 中央値を求める手続き(6) i=3 last=0 right=6 (12) 5 15 8 3 1 9 12 17 ソフトウェア実習I
5 3 1 15 8 9 12 17 中央値を求める手続き(7) last=2 交換結果 (14) i=5 last=2 right=6 (15) 5 3 1 15 8 9 12 17 (16) right=6 last=2 i=6 5 3 1 15 8 9 12 17 ソフトウェア実習I
中央値を求める手続き(8) (16) right=6 last=2 i=6 5 3 1 15 8 9 12 17 swap(v, 0, 1); swap(v, left, last); 最後の値とpivotを交換 last=2 何がわかったか? last<=3以下だから 中央値はつぎは どこの範囲ですか? (16) left=0 right=6 1 3 5 15 8 9 12 17 ソフトウェア実習I
問題 last=2 何がわかったか? last<=3以下だから 中央値はつぎは どこの範囲ですか? (16) left=0 right=6 1 3 5 15 8 9 12 17 sort(v, ?, ?); ソフトウェア実習I
解答 last=2 何がわかったか? last<=3以下だから 中央値はつぎは どこの範囲ですか? (16) left=0 right=6 1 3 5 15 8 9 12 17 sort(v, 3, 6); sort(v, , ); ソフトウェア実習I
前回の模範解答のバグになりそうな所に気が付きましたか?前回の模範解答のバグになりそうな所に気が付きましたか? • 中央値が入る場所: (MAX_DATA+(MAX_DATA%2))/2-1 • MAX_DATA/2 • 配列の個数が奇数の時(例 7個) • 中央値の入る場所=MAX_DATA/2 • 配列の個数が偶数の時(例 8個) • 中央値の入る場所≠MAX_DATA/2 • 関数sort内のif文の判定にMAX_DATA/2を使うのは,上記の理由で勧められない. ソフトウェア実習I