Taro-最大値探索法の開発(公開版

Similar documents
Taro-再帰関数Ⅱ(公開版).jtd

Taro-再帰関数Ⅲ(公開版).jtd

Taro-プログラミングの基礎Ⅱ(公

Taro-スタック(公開版).jtd

Taro-リストⅢ(公開版).jtd

Taro-リストⅠ(公開版).jtd

Taro-2分探索木Ⅱ(公開版).jtd

Taro-再帰関数Ⅰ(公開版).jtd

次に示す数値の並びを昇順にソートするものとする このソートでは配列の末尾側から操作を行っていく まず 末尾の数値 9 と 8 に着目する 昇順にソートするので この値を交換すると以下の数値の並びになる 次に末尾側から 2 番目と 3 番目の 1

kiso2-09.key

cp-7. 配列

Taro-2分探索木Ⅰ(公開版).jtd

C言語によるアルゴリズムとデータ構造

< F2D837C E95CF CF68A4A94C5816A2E6A>

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

Taro-ビット処理(公開版).jtd

memo

(search: ) [1] ( ) 2 (linear search) (sequential search) 1

memo

I. Backus-Naur BNF : N N 0 N N N N N N 0, 1 BNF N N 0 11 (parse tree) 11 (1) (2) (3) (4) II. 0(0 101)* (

Microsoft PowerPoint - 計算機言語 第7回.ppt

Microsoft PowerPoint - algo ppt [互換モード]

Microsoft PowerPoint - C言語の復習(配布用).ppt [互換モード]

C のコード例 (Z80 と同機能 ) int main(void) { int i,sum=0; for (i=1; i<=10; i++) sum=sum + i; printf ("sum=%d n",sum); 2

DA13

Taro-ファイル処理(公開版).jtd

新版明解C言語 実践編

Microsoft PowerPoint - lec4.ppt

Taro-数値計算の基礎Ⅱ(公開版)

I. Backus-Naur BNF S + S S * S S x S +, *, x BNF S (parse tree) : * x + x x S * S x + S S S x x (1) * x x * x (2) * + x x x (3) + x * x + x x (4) * *

:30 12:00 I. I VI II. III. IV. a d V. VI

Microsoft Word - 3new.doc

Taro-ポインタ変数Ⅰ(公開版).j

Microsoft PowerPoint - 05.pptx

情報処理Ⅰ

PowerPoint プレゼンテーション

プログラミング基礎

プログラミング実習I

Microsoft PowerPoint - 10.ppt [互換モード]

Microsoft PowerPoint - C4(反復for).ppt

今回のプログラミングの課題 ( 前回の課題で取り上げた )data.txt の要素をソートして sorted.txt というファイルに書出す ソート (sort) とは : 数の場合 小さいものから大きなもの ( 昇順 ) もしくは 大きなものから小さなもの ( 降順 ) になるよう 並び替えること

6 関数 6-1 関数とは少し長いプログラムを作るようになると 同じ処理を何度も行う場面が出てくる そのたびに処 理を書いていたのでは明らかに無駄であるし プログラム全体の見通しも悪くなる そこで登場す るのが 関数 である 関数を使うことを 関数を呼び出す ともいう どのように使うのか 実際に見て

PowerPoint プレゼンテーション

:30 12:00 I. I VI II. III. IV. a d V. VI

Microsoft Word - no206.docx

Microsoft PowerPoint - 4.pptx

main

関数の呼び出し ( 選択ソート ) 選択ソートのプログラム (findminvalue, findandreplace ができているとする ) #include <stdiu.h> #define InFile "data.txt" #define OutFile "surted.txt" #def

Microsoft PowerPoint - ca ppt [互換モード]

Microsoft PowerPoint - lec10.ppt

プログラム言語及び演習Ⅲ

2

明解Javaによるアルゴリズムとデータ構造

関数の呼び出し ( 選択ソート ) 選択ソートのプログラム (findminvalue, findandreplace ができているとする ) #include <stdio.h> #define InFile "data.txt" #define OutFile "sorted.txt" #def

PG13-6S

gengo1-11

<4D F736F F D20438CBE8CEA8D758DC03389F0939A82C282AB2E646F63>

Microsoft PowerPoint - kougi10.ppt

数値計算法

始めに, 最下位共通先祖を求めるための関数 LcaDFS( int v ) の処理を記述する. この関数は値を返さない再帰的な void 関数で, 点 v を根とする木 T の部分木を深さ優先探索する. 整数の引数 v は, 木 T の点を示す点番号で, 配列 NodeSpace[ ] へのカーソル

02

プログラミング基礎

Microsoft Word - no15.docx

演習課題No12

slide5.pptx

1. 入力した正の整数を降順に並べ換えて出力するプログラムを作成せよ プログラムは個別にコンパイルし make コマンドで実行すること 入力データは 50 以下とし 以下の数が混在しているとする 16 進数 : 先頭 1 文字が x または X( エックスの小文字か大文字 ) 8 進数 : 先頭 1

[1] #include<stdio.h> main() { printf("hello, world."); return 0; } (G1) int long int float ± ±

第2回

untitled

Microsoft Word - 13

スライド 1

Microsoft Word - Cプログラミング演習(9)

Prog1_10th

kiso2-06.key

memo

Microsoft PowerPoint - kougi9.ppt

Microsoft Word - Cプログラミング演習(10)

初歩のC言語ターミナル_2014_May.pages

Microsoft PowerPoint - 06.pptx

I ASCII ( ) NUL 16 DLE SP P p 1 SOH 17 DC1! 1 A Q a q STX 2 18 DC2 " 2 B R b

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科

C 言語講座 Vol 年 5 月 29 日 CISC

gengo1-8

Microsoft Word - Cプログラミング演習(8)

プログラミング基礎

C 2 / 21 1 y = x 1.1 lagrange.c 1 / Laglange / 2 #include <stdio.h> 3 #include <math.h> 4 int main() 5 { 6 float x[10], y[10]; 7 float xx, pn, p; 8 in

2

8 / 0 1 i++ i 1 i-- i C !!! C 2

演算増幅器

プログラミングI第10回

PowerPoint Presentation

£Ã¥×¥í¥°¥é¥ß¥ó¥°ÆþÌç (2018) - Â裵²ó ¨¡ À©¸æ¹½Â¤¡§¾ò·ïʬ´ô ¨¡

Microsoft Word - no13.docx

Microsoft Word - no12.doc

Microsoft PowerPoint - kougi11.ppt

1 return main() { main main C 1 戻り値の型 関数名 引数 関数ブロックをあらわす中括弧 main() 関数の定義 int main(void){ printf("hello World!!\n"); return 0; 戻り値 1: main() 2.2 C main

/* do-while */ #include <stdio.h> #include <math.h> int main(void) double val1, val2, arith_mean, geo_mean; printf( \n ); do printf( ); scanf( %lf, &v

PowerPoint プレゼンテーション

メソッドのまとめ

PowerPoint プレゼンテーション

Transcription:

最大値探索法の開発 0. 目次 1. 開発過程 1 目標 1 : 4 個のデータの最大値を求める 目標 2 : 4 個のデータの最大値を求める 改良 : 多数のデータに対応するため 配列を使う 目標 3 : n 個のデータの最大値を求める 改良 : コードを簡潔に記述するため for 文を使う 目標 4 : n 個のデータの最大値を求める 改良 : プログラムをわかりやすくするため 関数を使う 目標 5 : n 個のデータの最大値を求める 改良 : 処理を速くするため 最大値の位置のみを求め データの移動は最後に 1 回行う 移動するデータ量が多いときに有効 2. 開発過程 2 目標 1 : n 個のデータから 最大値とその次の値を求める 方法 : a[1] に 1 番目のデータを格納 a[2] に 2 番目のデータを格納する 目標 2 : n 個のデータの上位から m 番目まで求める 方法 : a[1] に 1 番目のデータを格納 a[2] に 2 番目のデータを格納 a[m] に m 番目のデータを格納する 3. 開発過程 3 目標 1 : n 個のデータから上位の m 個を求める 準備 : n 個のデータ中 適当な値 z 以上の要素の集まりと z 以下の要素の集まりに分割する 目標 2 : n 個のデータ中 上位の m 個を求める 方法 : a[1]~ a[m] に 1 番目から m 番目のデータを格納する 必ずしも a[1] a[2] a[m] とならないことに注意 - 1 -

n 個のデータの中から最大値を求めるプログラム開発過程と発展問題の開発過程を考察する 1. 開発過程 1 最大値探索法の開発 目標 1 : 4 個のデータの最大値を求める プログラム (m111.c) 1 /* << m111.c >> */ 3 4 int main() { 5 int a,b,c,d, /* 入力データ */ 6 max; /* 最大値 */ 7 8 /* 入力データ a,b,c,dの読み込み */ 9 scanf("%d%d%d%d",&a,&b,&c,&d); 10 11 /* 探索前データの表示 */ 12 printf(" 探索前 : "); 13 printf("a=%d b=%d c=%d d=%d\n",a,b,c,d); 14 15 /* 最大値探索 */ 16 max = a; 17 if( b > max ) { max = b; } 18 if( c > max ) { max = c; } 19 if( d > max ) { max = d; } 20 21 /* 探索後データの表示 */ 22 printf(" 探索後 : "); 23 printf("a=%d b=%d c=%d d=%d\n",a,b,c,d); 24 printf(" 最大値 : %d\n",max); 25 } % cc m111.c 22 44 11 33 探索前 : a=22 b=44 c=11 d=33 探索後 : a=22 b=44 c=11 d=33 最大値 : 44 ( 考察 ) 問題のサイズが小さい場合で 処理のコードを書いてみると 繰り返し処理ができる部分等が見えてくる - 2 -

目標 2 : 4 個のデータの最大値を求める 改良 : 多数のデータに対応するため 配列を使う プログラム (m121.c) 1 /* << m121.c >> */ 3 4 int main() { 5 int a[5], /* 入力データ */ 6 i, 7 n, /* データの個数 */ 8 max; /* 最大値 */ 9 10 /* データの読み込み */ 11 n = 4; 12 for( i=1; i<=n; i++ ) { scanf("%d",&a[i]); } 13 14 /* 探索前データの表示 */ 15 printf(" 探索前 : "); 16 for( i=1; i<=4; i++ ) { printf("%3d",a[i]); } 17 printf("\n"); 18 19 /* 最大値探索 */ 20 max = a[1]; 21 if( a[2] > max ) { max = a[2]; } 22 if( a[3] > max ) { max = a[3]; } 23 if( a[4] > max ) { max = a[4]; } 24 25 /* 探索後データの表示 */ 26 printf(" 探索後 : "); 27 for( i=1; i<=4; i++ ) { printf("%3d",a[i]); } 28 printf("\n"); 29 printf(" 最大値 : %d\n",max); 30 } % cc m121.c 33 44 11 22 探索前 : 33 44 11 22 探索後 : 33 44 11 22 最大値 : 44-3 -

目標 3 : n 個のデータの最大値を求める 改良 : コードを簡潔に記述するため for 文を使う プログラム (m131.c) 1 /* << m131.c >> */ 3 #include <stdlib.h> 4 #define N 999 /* データ個数の最大値 */ 5 6 int main() { 7 int a[n+1], /* 入力データ */ 8 i, 9 n, /* データの個数 */ 10 max; /* 最大値 */ 11 12 /* データの個数 nとデータの読み込み */ 13 scanf("%d",&n); 14 if( (n <= 0) (n > N) ) { exit(0); } 15 for( i=1; i<=n; i++ ) { scanf("%d",&a[i]); } 16 17 /* 探索前データの表示 */ 18 printf(" 探索前 : "); 19 for( i=1; i<=n; i++ ) { printf("%3d",a[i]); } 20 printf("\n"); 21 22 /* 最大値探索 */ 23 max = a[1]; 24 for( i=2; i<=n; i++ ) { 25 if( a[i] > max ) { max = a[i]; } 26 } 27 28 /* 探索後データの表示 */ 29 printf(" 探索後 : "); 30 for( i=1; i<=n; i++ ) { printf("%3d",a[i]); } 31 printf("\n"); 32 printf(" 最大値 : %d\n",max); 33 } % cc m131.c 8 66 44 22 88 33 11 55 77 探索前 : 66 44 22 88 33 11 55 77 探索後 : 66 44 22 88 33 11 55 77 最大値 : 88-4 -

目標 4 : n 個のデータの最大値を求める 改良 : プログラムをわかりやすくするため 関数を使う プログラム (m141.c) 1 /* << m141.c >> */ 3 #include <stdlib.h> 4 #define N 999 /* データ個数の最大値 */ 5 void max(int x[], int n); 6 7 int main() { 8 int a[n+1], /* 入力データ */ 9 i, 10 n; /* データの個数 */ 11 12 /* データの個数 nとデータの読み込み */ 13 scanf("%d",&n); 14 if( (n <= 0) (n > N) ) { exit(0); } 15 for( i=1; i<=n; i++ ) { scanf("%d",&a[i]); } 16 17 /* 探索前データの表示 */ 18 printf(" 探索前 : "); 19 for( i=1; i<=n; i++ ) { printf("%3d",a[i]); } 20 printf("\n"); 21 22 /* 最大値探索 最大値を a[1] に保存する */ 23 max(a,n); 24 25 /* 探索後データの表示 */ 26 printf(" 探索後 : "); 27 for( i=1; i<=n; i++ ) { printf("%3d",a[i]); } 28 printf("\n"); 29 printf(" 最大値 : %d\n",a[1]); 30 } 31 32 /* 関数 max */ 33 void max(int x[], int n) { 34 int i,w; 35 for( i=2; i<=n; i++ ) { 36 if( x[i] > x[1] ) { 37 w = x[1]; 38 x[1] = x[i]; 39 x[i] = w; 40 } 41 } 42 } - 5 -

% cc m141.c 8 33 77 55 44 11 88 22 66 探索前 : 33 77 55 44 11 88 22 66 探索後 : 88 33 55 44 11 77 22 66 最大値 : 88 目標 5 : n 個のデータの最大値を求める 改良 : 処理を速くするため 最大値の位置のみを求め データの移動は最後に 1 回行う 移動するデータ量が多いときに有効 プログラム (m151.c) 1 /* << m151.c >> */ 3 #include <stdlib.h> 4 #define N 999 /* データ個数の最大値 */ 5 void max(int x[], int n); 6 7 int main() { 8 int a[n+1], /* 入力データ */ 9 i, 10 n; /* データの個数 */ 11 12 /* データの個数 nとデータの読み込み */ 13 scanf("%d",&n); 14 if( (n <= 0) (n > N) ) { exit(0); } 15 for( i=1; i<=n; i++ ) { scanf("%d",&a[i]); } 16 17 /* 探索前データの表示 */ 18 printf(" 探索前 : "); 19 for( i=1; i<=n; i++ ) { printf("%3d",a[i]); } 20 printf("\n"); 21 22 /* 最大値探索 最大値を a[1] に保存する */ 23 max(a,n); 24 25 /* 探索後データの表示 */ 26 printf(" 探索後 : "); 27 for( i=1; i<=n; i++ ) { printf("%3d",a[i]); } 28 printf("\n"); 29 printf(" 最大値 : %d\n",a[1]); 30 } 31-6 -

32 /* 関数 max */ 33 void max(int x[], int n) { 34 int i, 35 j, /* 最大値が保存されている配列 x 内の位置 */ 36 w; 37 j = 1; 38 for( i=2; i<=n; i++ ) { 39 if( x[i] > x[j] ) { 40 /* 最大値の位置を保存する */ 41 j = i; 42 } 43 } 44 /* データの移動 */ 45 w = x[1]; x[1] = x[j]; x[j] = w; 46 } % cc m151.c 8 44 66 33 77 88 55 11 22 探索前 : 44 66 33 77 88 55 11 22 探索後 : 88 66 33 77 44 55 11 22 最大値 : 88-7 -

2. 開発過程 2 問題を一般化していく 目標 1 : n 個のデータから 最大値とその次の値を求める 方法 : a[1] に 1 番目のデータを格納 a[2] に 2 番目のデータを格納する プログラム (m211.c) 1 /* << m211.c >> */ 3 #include <stdlib.h> 4 #define N 999 /* データ個数の最大値 */ 5 void max(int x[], int n); 6 7 int main() { 8 int a[n+1], /* 入力データ */ 9 i, 10 n; /* データの個数 */ 11 12 /* データの個数 nとデータの読み込み */ 13 scanf("%d",&n); 14 if( (n <= 0) (n > N) ) { exit(0); } 15 for( i=1; i<=n; i++ ) { scanf("%d",&a[i]); } 16 17 /* 探索前データの表示 */ 18 printf(" 探索前 : "); 19 for( i=1; i<=n; i++ ) { printf("%3d",a[i]); } 20 printf("\n"); 21 22 /* n 個のデータから 最大値とその次の値を探索 */ 23 max(a,n); 24 25 /* 探索後データの表示 */ 26 printf(" 探索後 : "); 27 for( i=1; i<=n; i++ ) { printf("%3d",a[i]); } 28 printf("\n"); 29 } 30 31 /* 関数 max */ 32 void max(int x[], int n) { 33 int i,j,w; 34 35 /* 1 番目のデータを求め x[1] に格納 */ 36 j = 1; 37 for( i=2; i<=n; i++ ) { 38 if( x[i] > x[j] ) { j = i; } - 8 -

39 } 40 w = x[1]; 41 x[1] = x[j]; 42 x[j] = w; 43 44 /* 2 番目のデータを求め x[2] に格納 */ 45 j = 2; 46 for( i=3; i<=n; i++ ) { 47 if( x[i] > x[j] ) { j = i; } 48 } 49 w = x[2]; 50 x[2] = x[j]; 51 x[j] = w; 52 } % cc m211.c 8 44 33 55 22 88 66 11 77 探索前 : 44 33 55 22 88 66 11 77 探索後 : 88 77 55 22 44 66 11 33 目標 2 : n 個のデータの上位から m 番目まで求める 方法 : a[1] に 1 番目のデータを格納 a[2] に 2 番目のデータを格納 a[m] に m 番目のデータを格納する プログラム (m221.c) 1 /* << m221.c >> */ 3 #include <stdlib.h> 4 #define N 999 /* データ個数の最大値 */ 5 void max(int x[], int n, int m); 6 7 int main() { 8 int a[n+1], /* 入力データ */ 9 i, 10 m, /* 上位から m 番目 */ 11 n; /* データの個数 */ 12 13 /* データの個数 nと m 番目とデータの読み込み */ 14 scanf("%d%d",&n,&m); 15 if( (n <= 0) (n > N) ) { exit(0); } 16 for( i=1; i<=n; i++ ) { scanf("%d",&a[i]); } - 9 -

17 18 /* 探索前データの表示 */ 19 printf("n=%d m=%d\n",n,m); 20 printf(" 探索前 : "); 21 for( i=1; i<=n; i++ ) { printf("%3d",a[i]); } 22 printf("\n"); 23 24 /* n 個のデータの上位から m 番目まで探索 */ 25 max(a,n,m); 26 27 /* 探索後データの表示 */ 28 printf(" 探索後 : "); 29 for( i=1; i<=n; i++ ) { printf("%3d",a[i]); } 30 printf("\n"); 31 } 32 33 /* 関数 max */ 34 void max(int x[], int n, int m) { 35 int i,j,k,w; 36 37 /* k 番目のデータを求め x[k] に格納 */ 38 for( k=1; k<=m; k++ ) { 39 j = k; 40 for( i=j+1; i<=n; i++ ) { 41 if( x[i] > x[j] ) { j = i; } 42 } 43 w = x[k]; 44 x[k] = x[j]; 45 x[j] = w; 46 } 47 } % cc m221.c 8 3 33 88 55 77 11 22 44 66 n=8 m=3 探索前 : 33 88 55 77 11 22 44 66 探索後 : 88 77 66 33 11 22 44 55-10 -

3. 開発過程 3 与えられた問題の条件を緩くすると ( 1 番目から m 番目まで 上位の m 個 ) 新たな解法が見えてくる 目標 1 : n 個のデータから上位の m 個を求める 準備 : n 個のデータ中 適当な値 z 以上の要素の集まりと z 以下の要素の集まりに分割する 考え方 12 個のデータ : 77 22 66 44 55 44 22 44 11 44 11 22 で考察する ほぼ中央 (6 番目 ) のデータ (44) に着目して 44 以上のデータを配列の先頭に 44 以下のデータを配列の末尾に分割する ( 手順 0 ) 範囲を 1 番目から 12 番目までとする 77 22 66 44 55 44 22 44 11 44 11 22 ( 手順 1 )1 番目から 44 以下のデータが見つかるまで右端方向に探索する 77 22 66 44 55 44 22 44 11 44 11 22 ( 手順 2 )12 番目から 44 以上のデータが見つかるまで左端方向に探索する 77 22 66 44 55 44 22 44 11 44 11 22 ( 手順 3 ) 見つかった両データを交換する ( 手順 4 ) 範囲を 3 番目から 9 番目までとする - 11 -

( 手順 1 )3 番目から 44 以下のデータが見つかるまで右端方向に探索する ( 手順 2 )9 番目から 44 以上のデータが見つかるまで左端方向に探索する ( 手順 3 ) 見つかった両データを交換する ( 手順 4 ) 範囲を 5 番目から 7 番目までとする ( 手順 1 )5 番目から 44 以下のデータが見つかるまで右端方向に探索する ( 手順 2 )7 番目から 44 以上のデータが見つかるまで左端方向に探索する ( 手順 3 ) 見つかった両データが同じ位置なので終了する 1 番目から 6 番目まで 44 以上 7 番目から 12 番目まで 44 以下 - 12 -

プログラム (m311.c) 1 /* << m311.c >> */ 3 #include <stdlib.h> 4 #define N 999 /* データ個数の最大値 */ 5 int div(int x[], int left, int right); 6 7 int main() { 8 int a[n+1], /* 入力データ */ 9 i, 10 n, /* データの個数 */ 11 p, 12 z; /* ほぼ中央の位置のデータ */ 13 14 /* データの個数 nと m 番目とデータの読み込み */ 15 scanf("%d",&n); 16 if( (n <= 0) (n > N) ) { exit(0); } 17 for( i=1; i<=n; i++ ) { scanf("%d",&a[i]); } 18 19 /* 分割前データの表示 */ 20 printf(" 分割前 : "); 21 for( i=1; i<=n; i++ ) { printf("%3d",a[i]); } 22 printf("\n"); 23 24 /* 分割 ほぼ中央の位置のデータ zを用いて分割し 25 左半分の右端の位置 pを求める */ 26 z = a[(1+n)/2]; 27 p = div(a,1,n); 28 29 /* 分割後データの表示 */ 30 printf(" 分割後 (%d 以上 ): ",z); 31 for( i=1; i<=p; i++ ) { printf("%3d",a[i]); } printf("\n"); 32 printf(" 分割後 (%d 以下 ): ",z); 33 for( i=1; i<=p; i++ ) { printf(" "); } 34 for( i=p+1; i<=n; i++ ) { printf("%3d",a[i]); } printf("\n"); 35 } 36 37 /* 関数 : x[left]~ x[right] の中で x[left]~ x[k] が x[(left+right)/2] 38 以上となる位置 kを返す */ 39 int div(int x[], int left, int right) { 40 int b,i,j,w; 41 42 /* 手順 0 */ 43 i = left; j = right; /* x[i]~ x[j] が探索範囲 */ 44 b = x[(i+j)/2]; 45 while( 1 ) { 46 47 /* 手順 1 */ 48 while( x[i] > b ) { i = i+1; } - 13 -

49 50 /* 手順 2 */ 51 while( x[j] < b ) { j = j-1; } 52 if( i >= j ) { break; } 53 54 /* 手順 3 */ 55 w = x[i]; x[i] = x[j]; x[j] = w; 56 57 /* 手順 4 */ 58 i++; j--; 59 } 60 61 /* i j の場合 x[n0]~ x[i-1] が b 以上である 62 i=j の場合 x[n0]~ x[i] が b 以上である */ 63 if( i == j ) { return i; } else { return i-1; } 64 } % cc m311.c 1 11 分割前 : 11 分割後 (11 以上 ): 11 分割後 (11 以下 ): 2 11 11 分割前 : 11 11 分割後 (11 以上 ): 11 分割後 (11 以下 ): 11 2 11 22 分割前 : 11 22 分割後 (11 以上 ): 22 分割後 (11 以下 ): 11 2 22 11 分割前 : 22 11 分割後 (22 以上 ): 22 分割後 (22 以下 ): 11 6 11 22 22 33 33 33 分割前 : 11 22 22 33 33 33 分割後 (22 以上 ): 33 33 33 分割後 (22 以下 ): 22 22 11-14 -

目標 2 : n 個のデータ中 上位の m 個を求める 方法 : a[1]~ a[m] に 1 番目から m 番目のデータを格納する 必ずしも a[1] a[2] a[m] とならないことに注意 考え方 n=12 m=5 とする 探索前 : 11 22 33 44 55 33 22 44 55 44 11 22 与えられたデータから大きい順に 5 個の要素を選ぶ必要がある ほぼ中央 (6 番目 ) のデータ (33) に着目して 33 以上のデータと 33 以下のデータのグループに分割する 分割前 11 22 33 44 55 33 22 44 55 44 11 22 分割後 44 55 44 44 55 33 22 33 22 11 11 22 33 以上のグループの要素が 6 個となり 5 個より多いので 33 以上のグループから大きい順に 5 個の要素を選ぶ そこで 33 以上のグループのほぼ中央 (3 番目 ) のデータ (44) に着目し 44 以上のデータと 44 以下のデータのグループに分割する 分割前 44 55 44 44 55 33 分割後 55 55 44 44 44 33 44 以上のグループの要素が 3 個となり 5 個より少ないので 44 以下のグループから大きい順に 2 個の要素を選ぶ そこで 44 以下のグループの先頭から 2 番目のデータ (44) に着目し 44 以上のデータと 44 以下のデータのグループに分割する 分割前 44 44 33 分割後 44 44 33-15 -

44 以上のグループの要素が 1 個となり 2 個より少ないので 44 以下のグループから大きい順に 1 個の要素を選ぶ そこで 44 以下のグループの先頭から 1 番目のデータ (44) に着目し 44 以上のデータと 44 以下のデータのグループに分割する 分割前 44 33 分割後 44 33 44 以上のグループの要素が 1 個となり ちょうど 5 個選ばれた プログラム (m321.c) 1 /* << m321.c >> */ 3 #include <stdlib.h> 4 #define N 999 /* データ個数の最大値 */ 5 int div(int x[], int left, int right); 6 7 int main() { 8 int a[n+1], /* 入力データ */ 9 i, 10 k0,k1,k2, 11 m, 12 n, /* データの個数 */ 13 p; 14 15 /* データ個数と m 番目とデータの読み込み */ 16 scanf("%d%d",&n,&m); 17 if( (n <= 0) (n > N) (n < m) ) { exit(0); } 18 for( i=1; i<=n; i++ ) { scanf("%d",&a[i]); } 19 20 /* 分割前データの表示 */ 21 printf(" 分割前 : "); 22 for( i=1; i<=n; i++ ) { printf("%3d",a[i]); } 23 printf("\n"); 24 25 /* 大きいものから m 個を選ぶ */ 26 k0 = 1; k1 = n; k2 = m; 27 while ( 1 ) { 28 p = div(a,k0,k1); 29 if( p-k0+1 == k2 ) { break; } 30 if( p-k0+1 < k2 ) { 31 k2 = k2 - (p-k0+1); 32 k0 = p+1; 33 } else { 34 k1 = p-1; 35 } - 16 -

36 } 37 38 /* 選択後データの表示 */ 39 printf(" 選択後 (m=%d): ",m); 40 for( i=1; i<=m; i++ ) { printf("%3d",a[i]); } 41 printf(" --- "); 42 for( i=m+1; i<=n; i++ ) { printf("%3d",a[i]); } printf("\n"); 43 } 44 45 /* 関数 : x[left]~ x[right] の中で x[left]~ x[k] が x[(left+right)/2] 46 以上となる位置 kを返す */ 47 int div(int x[], int left, int right) { 48 49 < < 省略 > > 50 51 } % cc m321.cc 6 1 11 22 22 33 33 33 選択前 : 11 22 22 33 33 33 選択後 (m=1): 33 --- 33 33 22 22 11 6 2 11 22 22 33 33 33 選択前 : 11 22 22 33 33 33 選択後 (m=2): 33 33 --- 33 22 22 11 6 3 11 22 22 33 33 33 選択前 : 11 22 22 33 33 33 選択後 (m=3): 33 33 33 --- 22 22 11 6 4 11 22 22 33 33 33 選択前 : 11 22 22 33 33 33 選択後 (m=4): 33 33 33 22 --- 22 11 6 5 11 22 22 33 33 33 選択前 : 11 22 22 33 33 33 選択後 (m=5): 33 33 33 22 22 --- 11 6 6 11 22 22 33 33 33 選択前 : 11 22 22 33 33 33 選択後 (m=6): 33 33 33 22 22 11 --- - 17 -