[C言語] 文字列の配列をバブルソートする方法を解説
C言語で文字列の配列をバブルソートするには、文字列の比較と交換を行う必要があります。
文字列の比較には標準ライブラリの関数strcmp
を使用します。
この関数は、2つの文字列を比較し、同じ場合は0、最初の文字列が辞書順で小さい場合は負の値、大きい場合は正の値を返します。
バブルソートでは、隣接する文字列をstrcmp
で比較し、必要に応じて交換します。
この操作を配列の最後まで繰り返し、ソートが完了するまで続けます。
- 文字列の配列をバブルソートする手順
- 文字列の比較方法と注意点
- バブルソートの応用例とその実装方法
- バブルソートの利点と適用場面
- ソートの効率化のための工夫
文字列の配列をバブルソートする手順
ソートのための準備
バブルソートを実装する前に、まずはソート対象となる文字列の配列を準備します。
C言語では、文字列は文字の配列として扱われるため、文字列の配列は二次元配列として定義します。
以下に例を示します。
#include <stdio.h>
#include <string.h>
#define MAX_STRINGS 5
#define MAX_LENGTH 100
int main() {
// 文字列の配列を定義
char strings[MAX_STRINGS][MAX_LENGTH] = {
"りんご",
"バナナ",
"オレンジ",
"ぶどう",
"メロン"
};
// ここにソート処理を追加
return 0;
}
この例では、5つの文字列を持つ配列を定義しています。
それぞれの文字列は最大100文字まで格納可能です。
文字列の比較方法
文字列の比較には、strcmp関数
を使用します。
この関数は、2つの文字列を辞書順で比較し、以下のような結果を返します。
戻り値 | 意味 |
---|---|
< 0 | 第一引数の文字列が第二引数の文字列より小さい |
0 | 両方の文字列が等しい |
> 0 | 第一引数の文字列が第二引数の文字列より大きい |
この関数を利用して、文字列の順序を決定します。
バブルソートの実装手順
バブルソートは、隣接する要素を比較し、必要に応じて交換することでソートを行います。
以下に、文字列の配列をバブルソートするコードを示します。
#include <stdio.h>
#include <string.h>
#define MAX_STRINGS 5
#define MAX_LENGTH 100
int main() {
char strings[MAX_STRINGS][MAX_LENGTH] = {
"りんご",
"バナナ",
"オレンジ",
"ぶどう",
"メロン"
};
// バブルソートの実装
for (int i = 0; i < MAX_STRINGS - 1; i++) {
for (int j = 0; j < MAX_STRINGS - i - 1; j++) {
if (strcmp(strings[j], strings[j + 1]) > 0) {
// 文字列の交換
char temp[MAX_LENGTH];
strcpy(temp, strings[j]);
strcpy(strings[j], strings[j + 1]);
strcpy(strings[j + 1], temp);
}
}
}
// ソート結果の表示
printf("ソート後の文字列:\n");
for (int i = 0; i < MAX_STRINGS; i++) {
printf("%s\n", strings[i]);
}
return 0;
}
このコードでは、strcmp関数
を用いて隣接する文字列を比較し、必要に応じてstrcpy関数
で文字列を交換しています。
ソートの終了条件
バブルソートは、配列全体を走査し、交換が行われなくなるまで繰り返します。
上記のコードでは、for
ループを用いて、配列の要素数に基づいてソートを行っています。
具体的には、i
が0からMAX_STRINGS - 1
まで、j
が0からMAX_STRINGS - i - 1
までの範囲でループを回し、隣接する要素を比較します。
このようにして、バブルソートは配列の全ての要素が正しい順序になるまで繰り返されます。
完成したプログラム
以下に、文字列の配列をバブルソートする完成したプログラムを示します。
このプログラムは、5つの日本語の果物名を含む文字列の配列を辞書順にソートします。
#include <stdio.h>
#include <string.h>
#define MAX_STRINGS 5
#define MAX_LENGTH 100
int main() {
// 文字列の配列を定義
char strings[MAX_STRINGS][MAX_LENGTH] = {
"りんご",
"バナナ",
"オレンジ",
"ぶどう",
"メロン"
};
// バブルソートの実装
for (int i = 0; i < MAX_STRINGS - 1; i++) {
for (int j = 0; j < MAX_STRINGS - i - 1; j++) {
if (strcmp(strings[j], strings[j + 1]) > 0) {
// 文字列の交換
char temp[MAX_LENGTH];
strcpy(temp, strings[j]);
strcpy(strings[j], strings[j + 1]);
strcpy(strings[j + 1], temp);
}
}
}
// ソート結果の表示
printf("ソート後の文字列:\n");
for (int i = 0; i < MAX_STRINGS; i++) {
printf("%s\n", strings[i]);
}
return 0;
}
プログラムの実行例
ソート後の文字列:
オレンジ
バナナ
ぶどう
メロン
りんご
このプログラムは、strcmp関数
を使用して文字列を比較し、strcpy関数
を用いて文字列を交換することで、配列を辞書順にソートします。
実行結果として、果物名がアルファベット順に並び替えられたことが確認できます。
応用例
大文字小文字を区別しないソート
C言語で大文字小文字を区別しないソートを行うには、strcasecmp関数
を使用します。
この関数は、strcmp
と同様に文字列を比較しますが、大文字小文字を区別しません。
以下に例を示します。
#include <stdio.h>
#include <string.h>
#define MAX_STRINGS 5
#define MAX_LENGTH 100
int main() {
char strings[MAX_STRINGS][MAX_LENGTH] = {
"りんご",
"バナナ",
"オレンジ",
"ぶどう",
"メロン"
};
for (int i = 0; i < MAX_STRINGS - 1; i++) {
for (int j = 0; j < MAX_STRINGS - i - 1; j++) {
if (strcasecmp(strings[j], strings[j + 1]) > 0) {
char temp[MAX_LENGTH];
strcpy(temp, strings[j]);
strcpy(strings[j], strings[j + 1]);
strcpy(strings[j + 1], temp);
}
}
}
printf("大文字小文字を区別しないソート後の文字列:\n");
for (int i = 0; i < MAX_STRINGS; i++) {
printf("%s\n", strings[i]);
}
return 0;
}
ソート順を逆にする方法
ソート順を逆にするには、比較の条件を変更します。
strcmp関数
の戻り値を逆に評価することで、降順にソートできます。
if (strcmp(strings[j], strings[j + 1]) < 0) {
// 文字列の交換
char temp[MAX_LENGTH];
strcpy(temp, strings[j]);
strcpy(strings[j], strings[j + 1]);
strcpy(strings[j + 1], temp);
}
特定の文字列を優先するソート
特定の文字列を優先してソートするには、カスタムの比較関数を作成します。
例えば、「りんご」を最優先にする場合、以下のように実装します。
int customCompare(const char *a, const char *b) {
if (strcmp(a, "りんご") == 0) return -1;
if (strcmp(b, "りんご") == 0) return 1;
return strcmp(a, b);
}
この関数をバブルソート内で使用します。
部分的なソートの実装
配列の一部だけをソートする場合、ソート範囲を指定してバブルソートを実行します。
例えば、配列の最初の3つの要素だけをソートする場合、ループの範囲を調整します。
for (int i = 0; i < 3 - 1; i++) {
for (int j = 0; j < 3 - i - 1; j++) {
if (strcmp(strings[j], strings[j + 1]) > 0) {
char temp[MAX_LENGTH];
strcpy(temp, strings[j]);
strcpy(strings[j], strings[j + 1]);
strcpy(strings[j + 1], temp);
}
}
}
ソートの効率化のための工夫
バブルソートは効率が悪いことで知られていますが、いくつかの工夫で改善できます。
例えば、交換が行われなかった場合にソートを終了することで、無駄なループを避けることができます。
int swapped;
for (int i = 0; i < MAX_STRINGS - 1; i++) {
swapped = 0;
for (int j = 0; j < MAX_STRINGS - i - 1; j++) {
if (strcmp(strings[j], strings[j + 1]) > 0) {
char temp[MAX_LENGTH];
strcpy(temp, strings[j]);
strcpy(strings[j], strings[j + 1]);
strcpy(strings[j + 1], temp);
swapped = 1;
}
}
if (!swapped) break; // 交換がなければ終了
}
このように、バブルソートの基本的な実装に工夫を加えることで、特定の要件に応じたソートを実現できます。
よくある質問
まとめ
バブルソートは、シンプルで理解しやすいソートアルゴリズムであり、小規模なデータセットや教育目的に適しています。
この記事では、文字列の配列をバブルソートする方法を解説し、応用例や注意点についても触れました。
これを機に、他のソートアルゴリズムにも挑戦し、より効率的なプログラムを作成してみてください。