C言語に限らず、プログラミングの基本の一つ。値の並び替え。
とりあえずやってみたいという方や、学校の課題として出されたから作らないといけない・テストに出るから覚えないといけないという方も多いのではないでしょうか。
今回は、C言語を使って3つの整数を大きい順・小さい順に並び替えるプログラムの書き方を紹介していきます。
今回はわかりやすく整数値で並び替えしていますが、float型やdouble型といった小数を含む値でも並び替え可能です。
3つの整数を大きい順に並び替えるサンプル
まずは、関数化も何もせず力技で並び替えるサンプルコードから見ていきましょう。
#include <stdio.h>
int main() {
int data[] = { 1,3,2};
int temp; //値入れ替え用の一時変数
//0番目と1番目を比較
if (data[0] < data[1]) {
temp = data[0];
data[0] = data[1];
data[1] = temp;
}
//0番目と2番目を比較
if (data[0] < data[2]) {
temp = data[0];
data[0] = data[2];
data[2] = temp;
}
//1番目と2番目を比較
if (data[1] < data[2]) {
temp = data[1];
data[1] = data[2];
data[2] = temp;
}
//出力結果:data;[3,2,1]
printf("data:[%d,%d,%d]",data[0], data[1], data[2]);
return 0;
}
抑えておきたいポイントは7行目~12行目の処理です。
//0番目と1番目を比較
if (data[0] < data[1]) {
temp = data[0];
data[0] = data[1];
data[1] = temp;
}
まず配列の0番目と1番目を比較し、1番目のほうが大きければ0番目と入れ替える処理を行っています。
今回使用した配列の要素は[1,3,2]
なので、if文の結果は真。ここで値交換が行われ、配列の要素が[3,1,2]
になります。
次の14~19行目。配列0番目と2番目の値を比較して、2番目が大きかったら0番目と値を交換します。
//0番目と2番目を比較
if (data[0] < data[2]) {
temp = data[0];
data[0] = data[2];
data[2] = temp;
}
今回はdata[0]がdata[2]より大きいため値の交換は行われず、配列の要素[3,1,2]
のままです。
最後に配列の1番目と2番目を比較して、2番目のほうが大きかった場合は1番目と入れ替えます。
//1番目と2番目を比較
if (data[1] < data[2]) {
temp = data[1];
data[1] = data[2];
data[2] = temp;
}
今回はdata[1]がdata[2]より小さくif文の結果は真であるため、値の入れ替えが発生します。この値の交換によって配列の要素は[3,2,1]
となります。
3つの整数を大きい順に並び替える際は配列の0番目から順番に比較して入れ替えていくことで数字を大きい順に並び替えるプログラムが完成します。
小さい順はif文の条件を少し変えるだけでオーケー
3つの整数を小さい順に並び替えたい場合は、if文それぞれの>
を<
にしてあげるだけで並び替え規則を変更できます。
少し関数化してみる
先程のサンプルコードでは一切関数化せずに力技で実装しました。
続いては少しだけ関数化してコードを短くしてみましょう。
関数化できる箇所は、変数は異なるものの処理自体は全く同じ箇所です。
わかり易い例だと、値交換の部分ですね。
temp = data[0];
data[0] = data[1];
data[1] = temp;
値交換はサンプルコード中に3回登場していますが、いずれも参照している変数が異なるだけでやっている処理は全く同じです。
そのため以下のように関数化することが可能です。
void swap(int* a, int* b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
return;
}
こちらのswap関数を実装した上で、値交換の箇所をswap関数に置き換えてみましょう。少しコードがスッキリしたはずです。
#include <stdio.h>
void swap(int* a, int* b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
return;
}
int main() {
int data[] = { 1,3,2};
//0番目と1番目を比較
if (data[0] < data[1]) {
swap(&data[0],&data[1]);
}
//0番目と2番目を比較
if (data[0] < data[2]) {
swap(&data[0],&data[2]);
}
//1番目と2番目を比較
if (data[1] < data[2]) {
swap(&data[1],&data[2]);
}
//出力結果:data;[3,2,1]
printf("data:[%d,%d,%d]",data[0], data[1], data[2]);
return 0;
}
ポインタを使っているため参照渡ししている(変数の頭に&
がついている)ので注意してください
このように関数化することでコードが見やすくなります。
【応用編】並び替えの処理全て関数化する
ここからは応用編です。必要な方は頑張って覚えましょう。
先程は値交換の処理だけを関数化しましたが、続いては並び替えの処理全てを関数化し、値が入った配列を渡すだけで並び替えが完了する関数を作成してみました。
#include <stdio.h>
void swap(int* a, int* b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
return;
}
void sort(int* data) {
if (data[0] < data[1]) swap(&data[0], &data[1]);
if (data[0] < data[2]) swap(&data[0], &data[2]);
if (data[1] < data[2]) swap(&data[1], &data[2]);
return;
}
int main() {
int data[] = { 1,3,2};
sort(data);
//出力結果:data;[3,2,1]
printf("data:[%d,%d,%d]",data[0], data[1], data[2]);
return 0;
}
プログラムもかなりコンパクトになり、値交換が必要な配列がたくさん登場してもsort関数1回呼び出すだけで並び替えができるようになりました。
for文を組み合わせることで3つ以上の要素数にも対応できますが、まずはfor文を使わずどのような流れで値の比較・値交換ができるのか考えて、処理の流れを理解するようにしましょう。
しっかり理解しないままfor文を使って汎用性の高いコードを書いてしまうと、バグが出た時になぜバグが発生しているのか特定・修正が難しくなります。
処理の流れさえ理解できれば100個・1000個・10000個以上の要素を持つ配列をソートするプログラムの作成も自力でできるようになるはずです。
C言語をゼロから勉強するなら、まずはここまでできるように頑張ってみてください。