8.ソーティング(選択ソート・バブルソート)
8.1.ソーティングとは
ある集合に属する要素の有限列(同じ要素が2回以上現れてもよい)が与えられた時、与えられた順序に従って要素を並べ換えることを「ソーティング」と言います。例えば3の倍数からなる自然数集合に属する数10個を、小さい数から順に並べ替えることはソーティングです。 数字に限らず、文字列でも人間でも比較の方法さえ決まってさえいれば、ソーティングをすることができます。
8.2. 選択ソート(selection sort)
n個の数字を昇順(小さいもの順)に並べるアルゴリズムとして、最も単純なものは以下のようなものです。
- n個の中から最も小さい数字を探し、それを1番目の数字と入れ替える。
- 残りのn-1個の中から最も小さい数字を探し、それを2番目の数字と入れ替える。
- この処理をn-1回繰り返す。
このアルゴリズムを「選択ソート」(単純選択法)と呼びます。これを実装したサンプルプログラムを以下に示します。5〜12行目は乱数を発生させて指定個の数字を持つ配列を生成する関数で、14〜31行目は選択ソートを実行する関数、33〜38行目は配列内部の数字を表示する関数です。このサンプルを実行すると、最初に10個の乱数列が表示され、最後にソート後の数列が表示されます。
#include<stdio.h> #include<stdlib.h> #include<time.h> void create_array(int num[],int length){ int i; srand(time(NULL)); for(i=0;i<length;i++){ num[i]=rand()%100; } } void selection_sort(int num[],int length){ int i,n,tmp; int min,min_pos; for(i=0;i<length-1;i++){ min=num[i]; //仮の最小値を最初の数にセット min_pos=i; //仮の最小値の場所も覚える for(n=i+1;n<length;n++){ if(num[n]<min){ //比較対象の数字が仮の最小値より小さければ、仮の最小値をそれにする min=num[n]; min_pos=n; } } tmp=num[i]; //最小値と最初の数を入れ替え num[i]=min; num[min_pos]=tmp; } } void print_array(int num[],int length){ int i; for(i=0;i<length;i++){ printf("num[%d]=%d\n",i,num[i]); } } int main(int argc,char *argv[]){ int length=10; int num[length]; create_array(num,length); print_array(num,length); puts(""); selection_sort(num,length); print_array(num,length); return(0); }
(実習課題)
8.1のサンプルプログラムを改良しなさい。
- 2つのプログラムに分ける。1つは乱数を発生させて、ファイルに1行ずつ数字を書き込むプログラム(乱数発生プログラム)。もう1つは読み込んだファイルを選択ソートして、標準出力に出力するプログラム(選択ソートプログラム)。(乱数発生プログラムは後の章でも使用する)
- 乱数発生プログラムで実行時に指定されるオプションは、「発生させる数の個数」と「数字を書き込むファイル名」。発生させる数は1以上1000以下とする。
- 選択ソートプログラムで実行時に指定されるオプションは、「数字が書き込まれたファイル名」と「ソートする数の個数」(つまりファイルの行数)。
- 選択ソートプログラムでソーティングしている関数を、再帰呼び出しを使用するように改良する。
- (ヒント)n個の選択ソートとは、n個の中から最小のものを見つけ出した後、残りのn-1個に対して選択ソートを実行することである。
1 2 |
8.2.バブルソート
選択ソートは最小値を探すとき、「仮の最小値」と「仮の最小値の場所」の2つの情報を覚えていなければなりません。それらを覚えずにすむように改良したものが、「バブルソート」です。バブルソートのアルゴリズムは以下の通りです。今回もn個の数列を昇順に並べ替える場合を例にしています。
- n個の数の中から最小のものを1番目にする。その際、以下のようにする。
- n番目とn-1番目を比較し、n番目の方が小さければ入れ替える。
- n-1番目とn-2番目を比較し、n-1番目の方が小さければ入れ替える。
- 同様の処理をn-1回繰り返すと、1番目にn個の中から最も小さい数字がくる。
- 1番目を除いたn-1個の数に対して、上記の作業を行う。すると2番目にn-1個の中から最小の数字(つまりn個の中で2番目の小さい数字)がくる。
- 同様の処理をn-1回繰り返す。
数字が次々と先頭に移動していく処理の過程が、「泡が沸き立っていく」様子に似ていることから「バブルソート」と呼ばれています。
(実習課題)
以下のプログラムを作成しなさい。
- 「乱数発生プログラム」で生成された数列をファイルから読み取り、それに対してバブルソートを実行する。
- バブルソートでは再帰呼び出しを使用しないこと。
1 2 |
(実習課題)
以下のプログラムを作成しなさい。
- 「乱数発生プログラム」で生成された数列をファイルから読み取り、それに対してバブルソートを実行する。
- バブルソートでは再帰呼び出しを使用すること。
- (ヒント)n個の数列のバブルソートは、n個の中から最小の数を見つけた後、残りのn-1個に対してバブルソートを実行することである。
1 2 |