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

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

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

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

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

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

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

PG13-6S

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

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

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

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

< F2D837C E95CF CF68A4A94C5816A2E6A>

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

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

DA13

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

cp-7. 配列

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

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

memo

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

Microsoft PowerPoint - 4.pptx

プログラム例 /* ACM-ICPC2009 国内予選 Problem C */ // // filename = pc1.c // コンパイル

program7app.ppt

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

PowerPoint Presentation

memo

kiso2-09.key

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

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

データ構造

プログラミング実習I

情報処理Ⅰ

PowerPoint プレゼンテーション

論理と計算(2)

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


第9回 配列(array)型の変数

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

Microsoft PowerPoint - lec4.ppt

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

データ構造

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

memo

PowerPoint プレゼンテーション

Microsoft PowerPoint - 説明3_if文switch文(C_guide3)【2015新教材対応確認済み】.pptx

プログラミング基礎

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)* (

PowerPoint プレゼンテーション

Microsoft PowerPoint - C4(反復for).ppt

模擬試験問題(第1章~第3章)

Prog1_10th

PowerPoint プレゼンテーション

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

論理と計算(2)

CプログラミングI

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

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

2006年10月5日(木)実施

Microsoft Word - no12.doc

演習課題No12

Microsoft PowerPoint - lec10.ppt

Microsoft PowerPoint - kougi10.ppt

<4D F736F F D20438CBE8CEA8D758DC F0939A82C282AB2E646F63>

gengo1-11

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) * *

PowerPoint Presentation

4-4 while 文 for 文と同様 ある処理を繰り返し実行するためのものだが for 文と違うのは while 文で指定するのは 継続条件のみであるということ for 文で書かれた左のプログラムを while 文で書き換えると右のようになる /* 読込んだ正の整数値までカウントアップ (for

コマンドラインから受け取った文字列の大文字と小文字を変換するプログラムを作成せよ 入力は 1 バイトの表示文字とし アルファベット文字以外は変換しない 1. #include <stdio.h> 2. #include <ctype.h> /*troupper,islower,isupper,tol

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

プログラミング基礎

プログラミング方法論 II 第 14,15 回 ( 担当 : 鈴木伸夫 ) 問題 17. x 座標と y 座標をメンバに持つ構造体 Point を作成せよ 但し座標 は double 型とする typedef struct{ (a) x; (b) y; } Point; 問題 18. 問題 17 の

kiso2-06.key

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

Microsoft PowerPoint - 05.pptx

Microsoft PowerPoint - kougi9.ppt

memo

PowerPoint プレゼンテーション

<4D F736F F D20438CBE8CEA8D758DC03389F0939A82C282AB2E646F63>

/*Source.cpp*/ #include<stdio.h> //printf はここでインクルードして初めて使えるようになる // ここで関数 average を定義 3 つの整数の平均値を返す double 型の関数です double average(int a,int b,int c){

ポインタ変数

Microsoft PowerPoint - 11.pptx

[Problem F] 古い記憶 良さそうな方法は思いつかなかった アイディア募集中!!! かなり強引に解いている 各判定データに対して 30 秒程度かかる 元の文章と改ざん文章の関係を考える ウィルス感染の可能性は高々 2 回であり 各々の感染では 1 文字削除 1 文字追加 1 文字変更が行われ

C 言語第 3 回 2 a と b? 関係演算子 a と b の関係 関係演算子 等しい a==b 等しくない a!=b より大きい a>b 以上 a>=b より小さい a<b 以下 a<=b 状態 真偽 値 条件が満たされた場合 TRUE( 真 ) 1(0 以外 ) 条件が満たされなかった場合 F

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

Prog1_12th

C言語7

情報処理演習 B8クラス

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

Microsoft PowerPoint - 5Chap15.ppt

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

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

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

Microsoft Word - COMP-MATH-2016-FULLTEXT.doc

/* 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 プレゼンテーション

Microsoft Word - no206.docx

Microsoft Word - no15.docx

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

Microsoft PowerPoint - C_Programming(3).pptx

Transcription:

0. 目次 1 1. ソート 1 1. 1 挿入ソート 1 1. 2 クイックソート 1 1. 3 マージソート - 1 -

1 1. ソート 1 1. 1 挿入ソート 挿入ソートを再帰関数 isort を用いて書く 整列しているデータ (a[1] から a[n-1] まで ) に a[n] を挿入する操作を繰り返す 再帰的定義 isort(a[1],,a[n]) = insert(isort(a[1],,a[n-1]),a[n]) (n>1) = a[1] (n=1) n=5 の場合 isort(a[1],,a[5]) insert(isort(a[1],,a[4]),a[5]) isort(a[1],,a[4]) a[5] insert(isort(a[1],,a[3]),a[4]) isort(a[1],,a[3]) a[4] insert(isort(a[1],a[2]),a[3]) isort(a[1],a[2]) a[3] insert(isort(a[1]),a[2]) isort(a[1]) a[2] 動作例 insert(isort(a[1],,a[4]),a[5]) a[0] a[1] a[2] a[3] a[4] a[5] 11 22 44 55 33 1 a[5] を a[0] に代入 a[0] a[1] a[2] a[3] a[4] a[5] 33 11 22 44 55 33 2 a[0] と a[4] を比較 2 a[0] a[1] a[2] a[3] a[4] a[5] 33 11 22 44 55 55 3 a[4] を a[5] に代入 4 3 4 a[0] と a[3] を比較 a[0] a[1] a[2] a[3] a[4] a[5] 33 11 22 44 44 55 5 a[3] を a[4] に代入 6 5 6 a[0] と a[2] を比較 a[0] a[1] a[2] a[3] a[4] a[5] 33 11 22 33 44 55 7 a[0] を a[3] に代入 7-2 -

再帰的定義に基づくプログラムは次のように書ける プログラム (rf1111.c) 1 /* << rf1111.c >> */ 2 #include <stdio.h> 3 #define N 9999 /* データの最大個数 */ 4 int a[n+1]; /* データを格納する配列 */ 5 void isort(int k); 6 7 int main() { 8 int i, 9 n; /* データの個数 */ 10 11 while( 1 ) { 12 /* データの個数の読み込み */ 13 scanf("%d",&n); 14 if( (n <= 0) (n > N) ) { break; } 15 for( i=1; i<=n; i++ ) { scanf("%d",&a[i]); } 16 17 /* 整列前データの出力 */ 18 printf(" 整列前 : "); 19 for( i=1; i<=n; i++ ) { printf("%d ",a[i]); } 20 printf("\n"); 21 22 /* 並べ替え */ 23 isort(n); 24 25 /* 整列後データの出力 */ 26 printf(" 整列後 : "); 27 for( i=1; i<=n; i++ ) { printf("%d ",a[i]); } 28 printf("\n"); 29 } 30 } 31 /* 整列しているデータ (a[1] から a[k-1] まで ) に a[k] を挿入する関数 */ 32 void isort(int k) { 33 int i; 34 if( k > 1 ) { 35 isort(k-1); 36 /* 挿入操作 */ 37 a[0] = a[k]; 38 i = k-1; 39 while( a[i] > a[0] ) { 40 a[i+1] = a[i]; 41 i--; 42 } 43 a[i+1] = a[0]; 44 } 45 } - 3 -

実行結果 % cc rf1111.c %./a.out 6 55 22 33 11 66 44 整列前 : 55 22 33 11 66 44 整列後 : 11 22 33 44 55 66 0 プログラム (rf1111.c) において n が与えられたとき 配列 a[i](1 i n) がつぎのように定義されている a[i] = (11*i)%64 n=10 の場合 11,22,33,44,55,2,13,24,35,46 関数 isort が呼び出される回数 n 呼び出される回数 10 10 20 20 30 30 40 40-4 -

1 1. 2 クイックソート n 個のデータの並び a[1],a[2],,a[n] を適当な値を基準として 2 つに分割する 前者の並びのどの要素も 後者の並びのどの要素よりも小さいか等しくし 後者の並びのどの要素も前者の並びのどの要素よりも大きいか等しくする あとは 同様の分割をそれぞれの並びに対して 並びに含まれる要素の個数が 1 個以下になるまで行う このような考え方でデータを昇順に並べ換える方法をクイックソートという 並び {33,66,44,11,88,77,22,55} で具体的に示す ここで 並びの先頭の要素を適当な値とする 1 集合 {33,66,44,11,88,77,22,55} から適当な値 33 を選び 33 以下の集合 {33,11,22} と 33 以上の集合 {6,44,88,77,55} に分割する {33,66,44,11,88,77,22,55} {33,11,22} {66,44,88,77,55} 2 集合 {33,11,22} から適当な値 33 を選び 33 以下の集合 {11,22} と 33 以上の集合 {33} に分割する {33,66,44,11,88,77,22,55} {33,11,22} {66,44,88,77,55} {11,22} {33} 3 集合 {11,22} から適当な値 11 を選び 11 以下の集合 {11} と 11 以上の集合 {22} に分割する {33,66,44,11,88,77,22,55} {33,11,22} {66,44,88,77,55} {11,22} {33} {11} {22} - 5 -

4 集合 {66,44,88,77,55} から適当な値 66 を選び 66 以下の集合 {66,44,55} と 66 以上の集合 {88,77} に分割する {33,66,44,11,88,77,22,55} {33,11,22} { 66,44,88,77,55} {11,22} {33} {66,44,55} {88,77} {11} {22} 5 集合 {66,44,55} から適当な値 66 を選び 66 以下の集合 {44,55} と 66 以上の集合 {66} に分割する {33,66,44,11,88,77,22,55} {33,11,22} { 66,44,88,77,55} {11,22} {33} { 66,44,55} {88,77} {11} {22} {44,55} {66} 6 集合 {44,55} から適当な値 44 を選び 44 以下の集合 {44} と 44 以上の集合 {55} に分割する {33,66,44,11,88,77,22,55} {33,11,22} { 66,44,88,77,55} {11,22} {33} { 66,44,55} {88,77} {11} {22} {44,55} {66} {44} {55} - 6 -

7 集合 {88,77} から適当な値 88 を選び 88 以下の集合 {77} と 88 以上の集合 {88} に分割する {33,66,44,11,88,77,22,55} {33,11,22} { 66,44,88,77,55} {11,22} {33} { 66,44,55} {88,77} {11} {22} {44,55} {66} {77} {88} {44} {55} 8 このように分割された結果を枝分かれに沿って 反時計回りにたどっていき 1 個の要素からなる集合を出力する {33,66,44,11,88,77,22,55} {33,11,22} { 66,44,88,77,55} {11,22} {33} { 66,44,55} {88,77} {11} {22} {44,55} {66} {77} {88} {44} {55} プログラム (rf1120.c) 1 /* << rf1120.c >> */ 2 #include <stdio.h> 3 #define N 9999 /* データの最大個数 */ 4 int a[n+1]; /* データを格納する配列 */ 5 void qsort(int l, int r); 6 7 int main() { 8 int i, 9 n; /* データの個数 */ 10 11 while( 1 ) { 12 /* データの個数の読み込み */ 13 scanf("%d",&n); 14 if( (n <= 0) (n > N) ) { break; } 15 for( i=1; i<=n; i++ ) { scanf("%d",&a[i]); } 16-7 -

17 /* 整列前データ出力 */ 18 printf(" 整列前 : "); 19 for( i=1; i<=n; i++ ) { printf("%d ",a[i]); } printf("\n"); 20 21 /* 並べ替え */ 22 qsort(1,n); 23 24 /* 整列後データ出力 */ 25 printf(" 整列後 : "); 26 for( i=1; i<=n; i++ ) { printf("%d ",a[i]); } printf("\n"); 27 } 28 } 29 30 /* クイックソート */ 31 void qsort(int l, int r) { 32 int m,w; 33 if( l < r ) { 34 /* wを適当な値にして 配列 a[l]~ a[r] を 35 a[l]~ a[m] と a[m+1]~ a[r] に分割 */ 36 qsort(l,m); qsort(m+1,r); 37 } 38 return; 39 } qsort(a[1],,a[r]) qsort(a[l],,a[m]) qsort(a[m+1],,a[r]) - 8 -

解法 1 : 作業用配列を使う 配列 a[l]~ a[r] を この中のある値 w を基準に w 未満と w 以上に分割する このとき 作業用配列 b[] を用いる 動作例 l=3,r=7 a[l] から a[r] までを w=a[l]=55 で分割 a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] 22 11 55 66 44 77 33 99 88 w=a[3]=55 とする a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] w と a[4] を比較する 22 11 55 66 44 77 33 99 88 b[1] b[2] b[3] b[4] b[5] b[6] b[7] b[8] b[9] a[4] を b[7] に代入する 66 a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] w と a[5] を比較する 22 11 55 66 44 77 33 99 88 b[1] b[2] b[3] b[4] b[5] b[6] b[7] b[8] b[9] a[5] を b[3] に代入する 44 66 a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] w と a[6] を比較する 22 11 55 66 44 77 33 99 88 b[1] b[2] b[3] b[4] b[5] b[6] b[7] b[8] b[9] a[6] を b[6] に代入する 44 77 66 a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] w と a[7] を比較する 22 11 55 66 44 77 33 99 88 b[1] b[2] b[3] b[4] b[5] b[6] b[7] b[8] b[9] a[7] を b[4] に代入する 44 33 77 66 a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] w を b[5] に代入する 22 11 55 66 44 77 33 99 88 b[1] b[2] b[3] b[4] b[5] b[6] b[7] b[8] b[9] 44 33 55 77 66 a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] b[3] ~ b[7] を a[3] から 22 11 44 33 55 77 66 99 88 a[7] に代入する b[1] b[2] b[3] b[4] b[5] b[6] b[7] b[8] b[9] 44 33 55 77 66-9 -

解法 1 に基づくプログラムは次のように書ける プログラム (rf1121.c) 1 /* << rf1121.c >> */ 2 #include <stdio.h> 3 #define N 9999 /* データの最大個数 */ 4 int a[n+1], /* データを格納する配列 */ 5 b[n+1]; /* データを格納する配列 */ 6 void qsort(int l, int r); 7 8 int main() { 9 int i, 10 n; /* データの個数 */ 11 12 while( 1 ) { 13 /* データの個数とデータの読み込み */ 14 scanf("%d",&n); 15 if( (n <= 0) (n > N) ) { break; } 16 for( i=1; i<=n; i++ ) { scanf("%d",&a[i]); } 17 18 /* 整列前データの入力 */ 19 printf(" 整列前 : "); 20 for( i=1; i<=n; i++ ) { printf("%d ",a[i]); } 21 printf("\n"); 22 23 /* 並べ替え */ 24 qsort(1,n); 25 26 /* 整列後データの出力 */ 27 printf(" 整列後 : "); 28 for( i=1; i<=n; i++ ) { printf("%d ",a[i]); } 29 printf("\n"); 30 } 31 } 32 33 /* クイックソート */ 34 void qsort(int l, int r) { 35 int i,j,k; 36 if( l < r ) { 37 i = l; j = r; 38 /* a[l] を適当な値にして分割 */ 39 for( k=l+1; k<=r; k++ ) { 40 if( a[k] < a[l] ) { 41 b[i] = a[k]; 42 i++; 43 } else { 44 b[j] = a[k]; 45 j--; - 10 -

46 } 47 } 48 b[i] = a[l]; 49 /* b[l]~ b[i-1] が w 未満 b[i]=a[l] b[j+1]~ b[r] が w 以上 */ 50 for( k=l; k<=r; k++ ) { 51 a[k] = b[k]; 52 } 53 qsort(l,i-1); 54 qsort(j+1,r); 55 } 56 return; 57 } 実行結果 % cc rf1121.c %./a.out 5 11 11 11 11 11 整列前 : 11 11 11 11 11 整列後 : 11 11 11 11 11 5 11 22 33 44 55 整列前 : 11 22 33 44 55 整列後 : 11 22 33 44 55 6 55 22 33 11 66 44 整列前 : 55 22 33 11 66 44 整列後 : 11 22 33 44 55 66 0-11 -

解法 2 : 作業用配列を使わない 配列 a[l]~ a[r] を この中のある値 w を基準に w 以下と w 以上に分割する このとき 配列 a 内でつぎの交換を繰り返し 配列の左に w 以下の要素を集め 配列の右に w 以上の要素を集める 交換 : 配列 a に左方から w 以上の要素 x を見つけ 右方から w 以下の要素 y を見つける 要素 x と y を交換する 動作例 l=3,r=7 a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] w=a[3]=55 とする 22 11 55 66 44 77 33 99 88 iは w 以上の要素の位置 i j jは w 以下の要素の位置 a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] 22 11 55 66 44 77 33 99 88 a[3] と a[7] を交換する i j a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] 22 11 33 66 44 77 55 99 88 i j a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] 22 11 33 66 44 77 55 99 88 i j a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] 22 11 33 66 44 77 55 99 88 a[4] と a[5] を交換する i j a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] 22 11 33 44 66 77 55 99 88 j i 配列 a[3]~ a[4] の分割 配列 a[5]~ a[7] の分割へ進む - 12 -

交換操作 一般に起こる場合 交換 i j <wの場合 >wの場合 =wの場合 j i j i i j 交換 j i j i いずれも j 以下と i 以上に分割される 分割する範囲がすべて同じ値の場合 i j i j 交換 交換 i j i j 交換 交換 i j j i 交換 j 以下と i 以上に分割される j i j 以下と i 以上に分割される - 13 -

解法 2 に基づくプログラムは次のように書ける プログラム (rf1122.c) 1 /* << rf1122.c >> */ 2 #include <stdio.h> 3 #define N 9999 /* データの最大個数 */ 4 int a[n+1]; /* データを格納する配列 */ 5 void qsort(int l, int r); 6 7 int main() { 8 int i, 9 n; /* データの個数 */ 10 11 while( 1 ) { 12 /* データの個数とデータの読み込み */ 13 scanf("%d",&n); 14 if( (n <= 0) (n > N) ) { break; } 15 for( i=1; i<=n; i++ ) { scanf("%d",&a[i]); } 16 17 /* 整列前データの出力 */ 18 printf(" 整列前 : "); 19 for( i=1; i<=n; i++ ) { printf("%d ",a[i]); } 20 printf("\n"); 21 22 /* 並べ替え */ 23 qsort(1,n); 24 25 /* 整列後データ出力 */ 26 printf(" 整列後 : "); 27 for( i=1; i<=n; i++ ) { printf("%d ",a[i]); } 28 printf("\n"); 29 } 30 } 31 32 /* クイックソート */ 33 void qsort(int l, int r) { 34 int i,j,w,z; 35 if( l < r ) { 36 w = a[l]; /* wを適当な値 a[l] にして分割 */ 37 i = l; j = r; 38 do { 39 while( a[i] < w ) { i++; } 40 while( a[j] > w ) { j--; } 41 if( i <= j ) { 42 z = a[i]; a[i] = a[j] ; a[j] = z; 43 i++; j--; 44 } 45 } while( i <= j ); 46 qsort(l,j); 47 qsort(i,r); 48 } 49 return; 50 } - 14 -

実行結果 % cc rf1222.c %./a.out 5 11 11 11 11 11 整列前 : 11 11 11 11 11 整列後 : 11 11 11 11 11 5 11 22 33 44 55 整列前 : 11 22 33 44 55 整列後 : 11 22 33 44 55 6 55 22 33 11 66 44 整列前 : 55 22 33 11 66 44 整列後 : 11 22 33 44 55 66 0 プログラム (rf1122.c) において n が与えられたとき 配列 a[i](1 i n) がつぎのように定義されている a[i] = (11*i)%64 n=10 の場合 11,22,33,44,55,2,13,24,35,46 関数 qsort(1,n) が呼び出される回数 n 呼び出される回数 10 19 20 39 30 59 40 79 ( 考察 ) プログラム (rf1122.c) の 3 9 行目を以下のように変更して実行すると エラーになる 実行結果 while( a[j] >= w ) { j--; } % cc rf1122.c %./a.out 5 11 11 11 11 11 整列前 : 11 11 11 11 11 Segmentation Fault (core dumped) - 15 -

1 1. 3 マージソート 2 つのソートされたリスト ({a[i],,a[k]} と {a[k+1],,a[j]}) を 1 つのソートされたリストにまとめる関数を merge(a[i],,a[j]) とする 関数 merge を繰り返し使うソート法は マージソートと呼ばれ リスト {a[i],, a[j]} をソートする関数 msort は 次のように定義される 再帰的定義 msort(a[i],,a[j]) = merge(msort(a[i],,a[m]),msort(a[m+1],,a[j])) (i<j, i m<j) = a[i] (i=j) msort(a[i],,a[j]) merge(msort(a[i],,a[m]), msort(a[m+1],,a[j])) msort(a[i],,a[m]) msort(a[m+1],,a[j]) 動作例 merge(a[3],a[4],a[5],a[6],a[7]), i=3,j=7,m=(i+j)/2=5 a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] 22 11 55 66 44 77 33 99 88 a[3] から a[5] をソート a[6] から a[7] をソート a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] 22 11 44 55 66 33 77 99 88 a[3] から a[5] と a[6] から a[7] をマージ b[1] b[2] b[3] b[4] b[5] b[6] b[7] b[8] b[9] 33 44 55 66 77 作業用配列 b から配列 a に代入 a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] 22 11 33 44 55 66 77 99 88-16 -

再帰的定義に基づくプログラムは次のように書ける プログラム (rf1131.c) 1 /* << rf1131.c >> */ 2 #include <stdio.h> 3 #define N 9999 /* データの最大個数 */ 4 int a[n+1], /* データを格納する配列 */ 5 b[n+1]; /* 作業用配列 */ 6 void msort(int i, int j); 7 8 int main() { 9 int i, 10 n; /* データの個数 */ 11 12 /* データの個数 nとデータの読み込み */ 13 scanf("%d",&n); 14 for( i=1; i<=n; i++ ) { scanf("%d",&a[i]); } 15 16 /* 整列前データの出力 */ 17 printf(" 整列前 : "); 18 for( i=1; i<=n; i++ ) { printf("%3d",a[i]); } 19 printf("\n"); 20 21 /* 並べ替え */ 22 msort(1,n); 23 24 /* 整列後データ出力 */ 25 printf(" 整列後 : "); 26 for( i=1; i<=n; i++ ) { printf("%3d",a[i]); } 27 printf("\n"); 28 } 29 30 /* マージソート a[i] から a[j] を並べ替える */ 31 void msort(int i, int j) { 32 int f, /* 前半部の先頭位置 */ 33 g, /* 後半部の先頭位置 */ 34 k, /* 併合部の格納位置 */ 35 m; 36 if( i >= j ) { return; } 37 /* ほぼ中央の位置 mを求める */ 38 m = (i+j)/2; 39 /* 前半部 (a[i]~ a[m]) と後半部 (a[m+1]~ a[j]) をマージソート */ 40 msort(i,m); 41 msort(m+1,j); 42 /* 前半部と後半部をマージ */ 43 f = i; g = m+1; 44 k = f - 1; 45 while( 1 ) { 46 /* 前半部が空になったときの処理 */ - 17 -

47 if( f > m ) { 48 while( g <= j ) { 49 k++; b[k] = a[g]; g++; 50 }; 51 break; 52 } 53 /* 後半部が空になったときの処理 */ 54 if( g > j ) { 55 while( f <= m ) { 56 k++; b[k] = a[f]; f++; 57 }; 58 break; 59 } 60 k++; 61 if( a[f] <= a[g] ) { 62 b[k] = a[f]; f++; 63 } else { 64 b[k] = a[g]; g++; 65 } 66 } 67 /* 配列 bに保存された結果を配列 aに戻す */ 68 for( k=i; k<=j; k++ ) { a[k] = b[k]; } 69 } 実行結果 % cc rf1131.c %./a.out 2 11 22 整列前 : 11 22 整列後 : 11 22 %./a.out 2 22 11 整列前 : 22 11 整列後 : 11 22 %./a.out 3 11 22 33 整列前 : 11 22 33 整列後 : 11 22 33 %./a.out 3 33 22 11 整列前 : 33 22 11 整列後 : 11 22 33 %./a.out 9 99 11 88 22 77 33 66 44 55 整列前 : 99 11 88 22 77 33 66 44 55 整列後 : 11 22 33 44 55 66 77 88 99-18 -

プログラム (rf1131.c) において n が与えられたとき 配列 a[i](1 i n) がつぎのように定義されている a[i] = (11*i)%64 n=10 の場合 11,22,33,44,55,2,13,24,35,46 関数 msort が呼び出される回数 n 呼び出される回数 10 19 20 39 30 59 40 79-19 -