【基本情報技術者試験】バブルソートで比べる C・Go・Kotlin ~同じアルゴリズムでも書き方はこんなに変わる~

スポンサーリンク
C言語

はじめに

1回目の記事ではバブルソートのトレースを、2回目の記事では線形探索・二分探索のトレースを、それぞれC言語で確認した。3回目となる今回は少し趣向を変えて、1回目で書いたバブルソートを、GoとKotlinに移植してみる

アルゴリズムの中身(ロジック)は3言語ともまったく同じである。違うのは「書き方」だけ。同じ処理でも言語によってこんなに表情が変わる、という点を楽しみながらみていこう。

3言語のコード

C言語版(おさらい)

void bubble_sort(int arr[], int size) {
    for (int i = 0; i < size - 1; i++) {
        int swapped = 0;

        for (int j = 0; j < size - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                swapped = 1;
            }
        }

        if (swapped == 0) {
            break;
        }
    }
}

Go版

func bubbleSort(arr []int) {
    n := len(arr)

    for i := 0; i < n-1; i++ {
        swapped := false

        for j := 0; j < n-1-i; j++ {
            if arr[j] > arr[j+1] {
                arr[j], arr[j+1] = arr[j+1], arr[j]
                swapped = true
            }
        }

        if !swapped {
            break
        }
    }
}

Kotlin版

fun bubbleSort(arr: IntArray) {
    val n = arr.size

    for (i in 0 until n - 1) {
        var swapped = false

        for (j in 0 until n - 1 - i) {
            if (arr[j] > arr[j + 1]) {
                arr[j] = arr[j + 1].also { arr[j + 1] = arr[j] }
                swapped = true
            }
        }

        if (!swapped) {
            break
        }
    }
}

比較ポイント①:値の交換処理

同じ「隣同士の値を交換する」という処理だが、書き方は3者3様である。

言語書き方特徴
Ctemp を使って3行で交換一時変数を自分で用意する必要がある、最も基本的な書き方
Goarr[j], arr[j+1] = arr[j+1], arr[j]多重代入で1行にまとめられる
Kotlinarr[j] = arr[j + 1].also { arr[j + 1] = arr[j] }also を使うと一時変数なしで書けるが、慣れないと逆に読みにくい

Cのように一時変数を使う書き方は、実は多くの言語で「一番読みやすい書き方」として好まれることも多く、Go/Kotlinのような糖衣構文は「短く書けるが読みやすさとのトレードオフがある」という点も意識しておくと、単なる「新しい書き方の方が優れている」という誤解が避けられる。

比較ポイント②:配列の長さの扱い

  • C#define SIZE のように、配列の長さを自分で管理する必要がある(配列自体はサイズ情報を持たない)
  • Go:スライス([]int)は内部にサイズ情報を持っているので、len(arr) でいつでも取得できる
  • KotlinIntArray も同様に arr.size でサイズを取得できる

C言語で「なぜ配列の長さを別の変数で管理しないといけないのか」を理解してからGo/Kotlinを見ると、「配列自体が長さを知っている」という設計のありがたみが実感しやすくなる。

比較ポイント③:ループの書き方

3言語とも「二重ループ」という構造自体は同じだが、範囲の指定方法に違いがある。

  • Cfor (int j = 0; j < size - 1 - i; j++) のように、開始・条件・更新式を自分で書く
  • Gofor j := 0; j < n-1-i; j++ とほぼ同じ書き方ができる(Cに近い)
  • Kotlinfor (j in 0 until n - 1 - i) という範囲式(Range)を使う書き方になる

GoはCと文法がかなり近いため、「Cが読めればGoも読める」という感覚を持ちやすい言語である。一方Kotlinは until のような専用の構文が用意されており、C系の言語とは少し異なる構文になっている。

まとめ

  • アルゴリズムのロジックそのものは3言語で完全に同じ
  • 違うのは「言語がどんな書き方を用意してくれているか」という部分
  • Goは比較的Cに近い書き味、Kotlinは独自の糖衣構文が多く対照的

同じアルゴリズムを複数の言語で書き比べると、「このアルゴリズムの本質は何か」と「この言語らしい書き方は何か」を切り分けて理解できるようになる。今後も、線形探索・二分探索のGo/Kotlin移植や、Cで学んだ他のアルゴリズムの多言語比較を続けていく予定である。


この記事で扱ったコードは、GitHubの c-language-studies リポジトリ(FE-algorithm/01_bubble_sort/go/FE-algorithm/01_bubble_sort/kotlin/)で公開している。

コメント

タイトルとURLをコピーしました