【C言語】文字列のソートを行うプログラムの作り方

文字列をソートするプログラムの作り方の解説ページアイキャッチ

このページでは、C言語において、文字列を “アルファベット順にソートする” プログラムの作成方法について解説していきます。

ソートする方法としてはたくさんのアルゴリズムが提案されており、私のサイトでも下記のリンク先で代表的なソートアルゴリズムの解説を行なっています。

選択ソート解説ページのアイキャッチ選択ソートを図を使って分かりやすく解説(C言語サンプルプログラム付き) クイックソート解説ページのアイキャッチクイックソートを図を使って分かりやすく解説(C言語サンプルプログラム付き) マージソート解説ページのアイキャッチマージソートを図を使って分かりやすく解説(C言語サンプルプログラム付き) 挿入ソートの解説ページアイキャッチ挿入ソートを図を使って分かりやすく解説(C言語サンプルプログラム付き) ヒープソートの解説ページアイキャッチヒープソートを図を使って分かりやすく解説(C言語サンプルプログラム付き)

上記のリンク先ではソートアルゴリズムをC言語で実装したプログラムも紹介していますが、全てソートするデータは「数値」としています。より具体的にいうと int 型のデータをソートするプログラムになっています。

他のサイトで紹介されているソートアルゴリズムのプログラムでも同様で、int 型のデータをソートするものが多いです。

なので、そのままだと文字列のソートが行えません。

ただし、これらはちょっと変更するだけで文字列をソートするプログラムに変更することができます(アルファベット順にソート)。

要は上記のリンク先で紹介しているソートアルゴリズムも、ちょっと変更すれば文字列のソートに適用できるということです。

また、「数値をソートするプログラム」と「文字列をソートするプログラム」では、後者の方が作るのが難しいです。

そのため、文字列をソートするプログラムを作る場合でも、まずは数値をソートするプログラムを作成し、そこから文字列をソートするプログラムに仕立てていく方が楽です。

上記のような観点に基づき、このページでは、文字列をソートするプログラムを作るために、数値をソートするプログラムに対してどのような変更を行えば良いかについて解説していきたいと思います。

数値をソートするプログラムの作り方自体は、適用したいアルゴリズムに合わせて上記のリンク先を参照していただければと思います。

数値をソートするプログラムと文字列をソートするプログラムの違い

まずは数値(int 型のデータ)をソートするプログラムと、それを文字列ソート用に変更したプログラムの実例を紹介したいと思います。

この2つのプログラムの「差分」が、数値をソートするプログラムを文字列をソートするプログラムに仕立てていくために “必要な変更点” となります。

今回は例として、下記ページで紹介している「選択ソート」のプログラム(再帰処理なしの方)と、これを文字列ソート用に変更したものを紹介します。

選択ソート解説ページのアイキャッチ選択ソートを図を使って分かりやすく解説(C言語サンプルプログラム付き)

上記ページでは「選択ソート」を行う関数のみを紹介していましたが、今回はソートするデータを格納するところもポイントになるので、プログラム全体のソースコードを紹介します。

数値のソートプログラム

選択ソートで数値のソートを行うプログラムのソースコードは次のようなものになります。

数値のソート
#include <stdio.h>

/* データの数 */
#define NUM 12

/* 配列のデータを表示する関数 */
void printArray(int a[], int num){
    int i;
    for (i = 0; i < num; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");
}

/* 選択ソートを行う関数
 * data[] : ソートを行うデータの集合
 *          (ソート後のデータの集合を格納)
 * left : ソートを行う範囲の開始点
 * right : ソートを行う範囲の終了点
 */
void selectionSort(int data[], int left, int right) {
    int start;
    int i;
    int min;
    int i_min;
    int tmp;

    /* データ数が1の場合はソート済みなのでソート終了 */    
    if (left == right) {
        return;
    }

    /* ソート範囲(開始点)の初期化 */
    start = left;

    /* ソート範囲を狭めながらソート処理 */
    for (start = left; start < right; start++) {

        /* ひとまずソート範囲の先頭を最小値とみなす */
        i_min = start;
        min = data[i_min];

        /* ソート範囲の中から最小値を探索 */
        for (i = start; i <= right; i++) {
            if (min > data[i]) {
                /* 最小値とその値を持つインデックスを更新 */
                min = data[i];
                i_min = i;
            }
        }
        /* ソート範囲の先頭と最小値を交換 */
        tmp = data[start];
        data[start] = data[i_min];
        data[i_min] = tmp;
    }
}


int main(void) {
    /* ソートするデータ */
    int array[NUM] = {
        10, 5, 4, 11, 1, 8, 2, 3, 7, 9, 12, 6
    };

    /* ソートするデータの個数 */
    int data_num = NUM;

    /* ソート前の配列の表示 */
    printArray(array, data_num);

    /* マージソート */
    selectionSort(array, 0, data_num - 1);

    /* ソート後の配列の表示 */
    printArray(array, data_num);

    return 0;
}

実行すると、下記のように 1 から 12 までの数値が昇順にソートされた状態で表示され、数値がソートされていることが確認できると思います。

10 5 4 11 1 8 2 3 7 9 12 6 
1 2 3 4 5 6 7 8 9 10 11 12

スポンサーリンク

文字列のソートプログラム

そして、上記の数値のソートプログラムを文字列のソート用に変更したプログラムのソースコードが次のようになります。

文字列のソート
#include <stdio.h>
#include <string.h>


/* データの数 */
#define NUM 12

/* 文字列の最大サイズ */
#define STR_MAX 256

/* 配列のデータを表示する関数 */
void printArray(char a[][STR_MAX], int num){
    int i;
    for (i = 0; i < num; i++) {
        printf("%s ", a[i]);
    }
    printf("\n");
}


/* 選択ソートを行う関数
 * data[][STR_MAX] : ソートを行うデータの集合
 *                  (ソート後のデータの集合を格納)
 * left : ソートを行う範囲の開始点
 * right : ソートを行う範囲の終了点
 */
void selectionSort(char data[][STR_MAX], int left, int right) {
    int start;
    int i;
    char min[STR_MAX];
    int i_min;
    char tmp[STR_MAX];

    /* データ数が1の場合はソート済みなのでソート終了 */    
    if (left == right) {
        return;
    }

    /* ソート範囲(開始点)の初期化 */
    start = left;

    /* ソート範囲を狭めながらソート処理 */
    for (start = left; start < right; start++) {

        /* ひとまずソート範囲の先頭を最小値とみなす */
        i_min = start;
        strcpy(min, data[i_min]);

        /* ソート範囲の中から最小値を探索 */
        for (i = start; i <= right; i++) {
            if (strcmp(min, data[i]) > 0) {
                /* 最小値とその値を持つインデックスを更新 */
                strcpy(min, data[i]);
                i_min = i;
            }
        }

        if (start != i_min) {

            /* ソート範囲の先頭と最小値を交換 */
            strcpy(tmp, data[start]);
            strcpy(data[start], data[i_min]);
            strcpy(data[i_min], tmp);
        }
    }
}

int main(void) {
    /* ソートするデータ */
    char array[NUM][STR_MAX] = {
        "January",
        "Feburary",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "Nobember",
        "December"
    };

    /* ソートするデータの個数 */
    int data_num = NUM;

    /* ソート前の配列の表示 */
    printArray(array, data_num);

    /* 選択ソート */
    selectionSort(array, 0, data_num - 1);

    /* ソート後の配列の表示 */
    printArray(array, data_num);

    return 0;
}

実行すると、下記のように1月から12月を英語で表した文字列がアルファベット的に昇順にソートされた状態で表示され、文字列がソートされていることが確認できると思います。

January Feburary March April May June July August September October Nobember December 
April August December Feburary January July June March May Nobember October September 

では、具体的に “どのような変更をすることで文字列のソートに対応させたのか?” について続けて解説していきたいと思います。

文字列ソートプログラムの作り方

ここからは、文字列ソートプログラムの作り方、より具体的には数値をソートするプログラムを文字列をソートするプログラムに変更する方法を解説していきたいと思います。

要は、数値をソートするプログラムと文字列をソートするプログラムの違いで紹介した2つのソースコードの違いが、数値をソートするプログラムから文字列をソートするプログラムを仕立てる上で必要になる変更点になります。

大きく分けると下記の3つになります。

  • データを char 型の配列に格納するようにする
  • 大小関係の比較は strcmp 関数で行う
  • 代入は strcpy 関数に置き換える

データを char 型の配列に格納するようにする

まず、文字列を扱う場合に、文字列を格納する変数がどのようなものであるかを考えてみましょう!

char 型の配列ですね!

もちろん char* 型(char のポインタ)でも扱うことはできますが、今回は char 型の配列で文字列を扱うものとして説明したいと思います。

したがって、int 型のデータをソートするプログラムを文字列ソートできるようにするには、まずデータを「char 型の配列」で扱うように変更する必要があります。

ソートしたいデータを char 型の2次元配列に格納するようにする

ソートを行うプログラムでは、ソートするデータを配列に格納し、その配列に格納されたデータをソートするものが多いです。

つまり、int 型のデータをソートするプログラムにおいては、int 型の配列にソートするデータを格納します。

例えば数値のソートプログラムでは、main 関数の先頭でソートするデータを下記のように int 型の配列に格納しています。

ソートする数値データの配列への格納
int array[NUM] = {
    10, 5, 4, 11, 1, 8, 2, 3, 7, 9, 12, 6
};

一方で、今回は文字列のデータをソートするので、文字列の配列にソートするデータを格納する必要があります。

文字列は前述の通り、char 型の配列に格納しますので、要するに、”char 型の配列” の配列にデータを格納する必要があることになります。

つまり、文字列をソートするためには、2次元配列を用意し、この2次元配列にソートしたいデータを格納するようにプログラムを変更する必要があります。

例えば文字列のソートプログラムでは、main 関数の先頭でソートするデータを下記のように char 型の2次元配列に格納しています。

ソートする文字列データの配列への格納
char array[NUM][STR_MAX] = {
    "January",
    "Feburary",
    "March",
    "April",
    "May",
    "June",
    "July",
    "August",
    "September",
    "October",
    "Nobember",
    "December"
};
MEMO

2次元のデータは「ダブルポインタ」や「ポインタの配列」などでも扱うことが可能ですが、今回は2次元データを扱うのに「2次元配列」を利用する前提で解説させていただいています

ソートする関数の引数の型を char 型の2次元配列に変更する

また、データを格納する型が変わるので、それに合わせて、そのデータをソートする関数の引数の型も変更する必要があります(これはソートする関数を main 関数から分離している場合のみです)。

例えば数値のソートプログラムでは、ソートを実行する selectionSort 関数の第1引数の型は「int 型の配列」になっています。

これは、この関数が int 型の配列に格納されたデータをソートするものだからです。

数値をソートする関数の引数
void selectionSort(int data[], int left, int right);

一方で、文字列をソートする場合は、文字列の配列に格納されたデータをソートする必要がありますので、ソートを実行する関数の引数もそれに合わせて変更してやる必要があります。

例えば文字列のソートプログラムでは、ソートを実行する selectionSort 関数の第1引数の型を下記のように「char 型の2次元配列」にしています。

文字列をソートする関数の引数
void selectionSort(char data[][STR_MAX], int left, int right);

ソートするデータを格納する変数を char 型の配列に変更する

また、実際にソートする際には、ソートするデータを格納した配列からデータを取得し、そのデータを変数に格納して一時的に記憶しておくような処理を行うことがあります。

例えば数値のソートプログラムでは、下記の部分で配列の2つの要素の交換を行うために、一時的に変数 tmp にデータを記憶させるような処理を行なっています。

数値のデータの交換
tmp = data[start];
data[start] = data[i_min];
data[i_min] = tmp;

こういった配列のデータを一時的に保存するような変数の型も、ソートするデータの型に合わせて変更してやる必要があります。文字列をソートする場合は、文字列を一時的に保存するため、char 型の配列に変更してやる必要があるということになります。

ただし、ソートする関数の “変数全て” が配列のデータを格納するための変数ではないので、どの変数の型を変更するかはしっかり見極める必要があります。

ソートを行う関数で扱う変数は、主に下記の2種類になると思います。

  • 配列の添字を管理する変数
  • ソートするデータを一時的に記憶する変数

前者の配列の添字を管理する変数は int 型や unsigned int 型などの整数型のままで良いです。

型を変更する必要があるのは後者の変数のみになります。

例えば数値のソートプログラムselectionSort 関数では下記の4つの変数を変数宣言しています。

数値をソートするために使用する変数
int start;
int i;
int min;
int i_min;
int tmp;

各変数を種類分けすると下記のように分けられます。

  • 配列の添字を管理する変数:startii_min
  • ソートするデータを一時的に記憶する変数:mintmp

そのため、文字列をソートする場合は、mintmp は文字列を扱える型、要は char 型の配列として宣言する必要があります。

例えば文字列のソートプログラムの selectionSort 関数の変数は下記のように変数宣言しています。

文字列をソートするために使用する変数
int start;
int i;
char min[STR_MAX];
int i_min;
char tmp[STR_MAX];

スポンサーリンク

大小関係の比較は strcmp 関数で行う

ソートを行う上で必要になるのが「大小関係の比較」です。

ソートの基本的な考え方は、ソートする各データの「大小関係の比較」を行い、その比較結果に基づいてデータを並べ替える処理です。

なので、基本的にソートを行うためには「大小関係の比較」が必要になります。

もちろん、文字列をソートする場合にも「大小関係の比較」を行う必要があります。

文字列における「大小関係の比較」って何?と思われる方もおられるかもしれませんが、文字列の場合は、要はアルファベット順的に前にあるのか後ろにあるかの比較になります。

数値の場合の大小関係の比較は簡単ですよね?

単に比較演算子で2つの値を比較すれば良いだけです。

数値の比較
int x;
int y;

/* xとyに数値を格納 */

/* 比較 */
if (x > y) {
    printf("xの方が大きいです\n");
} else {
    printf("yの方が大きいです\n");
}

一方で、文字列における「大小関係の比較」は難しそうに感じるかもしれません。ですが、実はこれは strcmp 関数を用いることで簡単に実現することができます。

strcmp は第1引数と第2引数とで与えられた文字列の比較を行う関数になります。

strcmp関数
#include <string.h>

int strcmp(const char *, const char *);

よく使うのが、2つの文字列が一致しているかどうかの確認です。

strcmp 関数は、2つの文字列が一致している場合は 0 を返却しますので、この戻り値から2つの文字列が一致しているかどうかを簡単に確認することができます。

文字列が一致しているかどうかの比較
char str1[256];
char str2[256];

/* str1とstr2に文字列を格納 */

/* 比較 */
if (strcmp(str1, str2) == 0) {
    printf("2つの文字列は同じです\n");
} else {
    printf("2つの文字列は異なります\n");
}

この strcmp 関数では2つの文字列が一致しているかどうかだけでなく、文字列の大小関係の比較も行うことが可能です。要は2つの文字列のどちらが「アルファベット順的に “前に” あるのか “後ろ” にあるのか」を確認することができます。

strcmp 関数では、第1引数の方が「アルファベット順的に “前に” 存在する場合」、戻り値として「0 よりも小さい値」を返却します。

つまり、下記の if 文が必ず成立します。

strcmpによる文字列の比較1
if (strcmp(str1, str2) < 0) {
    /* str1の方がアルファベット順的に前側に存在する場合 */
}

また、第2引数の方が「アルファベット順的に “後ろ” に存在する場合」、戻り値として「0 よりも大きい値」を返却します。

つまり、下記の if 文が必ず成立します。

strcmpによる文字列の比較2
if (strcmp(str1, str2) > 0) {
    /* str1の方がアルファベット順的に後ろ側に存在する場合 */
}

したがって、strcmp 関数を用いることで2つの文字列のどちらが「アルファベット順的に “前に” あるのか」or「アルファベット順的に “後ろ” にあるのか」を確認することができます。

で、これを利用することで、複数の文字列をアルファベット順でソートすることが可能になります。

例えば、文字列のソートプログラムの selectionSort 関数では、下記部分で strcmp 関数を用いて min に格納された文字列が data[i] に格納された文字列よりも「アルファベット順的に “後ろ” にあるのか」どうかを判断しています。

そして、min の文字列の方が後ろにある場合は、アルファベット順的に前に存在する data[i] の文字列を min に格納しています。

要は、ソートするデータの中で、「アルファベット順的に一番 “前に” 存在する」文字列を探すための処理になります。

ソートにおける文字列の大小関係の比較
if (strcmp(min, data[i]) > 0) {
    /* 最小値とその値を持つインデックスを更新 */
    strcpy(min, data[i]);
    i_min = i;
}

いくつか strcmp 関数の実例を示しておきます。

例えば下記の場合、2つの文字列は一致するので strcmp 関数は 0 を返却します。

strcmpの例1
strcmp("ABCD", "ABCD")

下記の場合は、第1引数の文字列の方が「アルファベット順的に “前に” 存在する」ので strcmp 関数は “0 よりも小さい値” を返却します。

具体的には、1文字目が第1引数の方が「アルファベット順的に “前に” 存在する」ので strcmp 関数は “0 よりも小さい値” を返却します。

strcmpの例2
strcmp("ABCD", "BBCD")

下記の場合も、第1引数の文字列の方が「アルファベット順的に “前に” 存在する」ので strcmp 関数は “0 よりも小さい値” を返却します。

今度は4文字目が第1引数の方が「アルファベット順的に “前に” 存在する」ので strcmp 関数は “0 よりも小さい値” を返却します。こんな感じで strcmp 関数は、各文字を先頭から比較し、最初に異なる文字の比較結果を返却してくれます。

strcmpの例3
strcmp("ABCD", "ABCE")

下記の場合は、第1引数の文字列の方が「アルファベット順的に “後ろに” 存在する」ので strcmp 関数は “0 よりも大きい値” を返却します。

具体的には、4文字目が第1引数の方が「アルファベット順的に “後ろに” 存在する」ので strcmp 関数は “0 よりも大きい値” を返却します。

strcmpの例4
strcmp("ABCE", "ABCD")

下記の場合は、第1引数の文字列の方が「アルファベット順的に “前に” 存在する」と判断されて strcmp 関数が “0 よりも小さい値” を返却します。

こんな感じで、一方の文字列がもう一方の文字列を途中で途切れた形になっている場合は、文字列の短い方が「アルファベット順的に “前に” 存在する」と判断されます。

また、この例のように、文字列長が異なる場合も strcmp 関数は正しく動作してくれます。

strcmpの例5
strcmp("ABC", "ABCD")

では、下記の場合はどうでしょう?この場合、strcmp 関数は “0 よりも大きい値” を返却します。

strcmpの例6
strcmp("a", "ZXY")

2つ文字列の1文字目の a と Z だと a の方が「アルファベット順的に “前に” 存在する」ように思えますが、返却されるのは “0 よりも大きい値” です。

ということは、strcmp 関数は a の方が「アルファベット順的に “後ろに” 存在する」と判断していることになります。

ここまで分かりやすいようにあえて strcmp 関数は「アルファベット順的に “前に” あるのか “後ろ” にあるのかを比較する」と説明してきましたが、実はこれは正確ではないです。

正確には「アスキーコード的に大きいか小さいか」の比較を行なっています。

アスキーコードというのは各文字に割り振られた数値のことをいいます。

どの文字にどんなアスキーコードが割り振られているかは下記ページが分かりやすいと思います。

https://www.k-cube.co.jp/wakaba/server/ascii_code.html

で、アルファベットの小文字は全て、どの大文字よりも大きいアスキーコードが割り振られています。

なので、第1引数を「”1文字目が小文字” の文字列」、第2引数を「”1文字目が大文字” の文字列」として strcmp 関数を実行した場合、必ず “0 よりも大きい値” が返却されることになります。

大文字と小文字を区別せずに、文字列をアルファベット順にソートしたいような場合は、2つの文字列両方を大文字もしくは小文字の文字列に統一してから strcmp 関数を実行する必要があることに注意してください。

大文字小文字の変換方法は下記ページでも解説していますので、ぜひ参考にしていただければと思います!

C言語での大文字 ⇔ 小文字変換の方法を解説

ここまで strcmp 関数で解説してきましたが、より文字列を安全に扱える strncmp 関数などを利用しても同様の「大小関係の比較」を行うこともできます。

代入は strcpy 関数に置き換える

では、最後のポイントである「代入を strcpy 関数に置き換える」について解説していきます。

int 型などの数値を扱う変数においては、その変数への数値の格納は、単に代入演算子(=)を用いて代入するだけで実現することができます。

int型変数への数値の格納
int x;

/* xへの数値の格納 */
x = 100;

ただし、文字列をソートする場合は扱うデータが文字列、つまり char 型の配列なので単に代入を行おうとするとコンパイルエラーが発生します(このような代入で文字列が格納できるのは、変数宣言時のみです)。

char型配列への文字列の格納(ダメな例)
char x[256];

/* xへの文字列の格納 */
x = "ABCDE";

char 型の配列に文字列を格納する場合は、代入演算子ではなく strcpy を利用する必要があります(strcpy 以外でも文字列の格納を実現する関数はありますが、ここでは一番簡単な strcpy 関数で説明していきます)。

strcpy 関数では、第1引数で指定した char 型の配列に、第2引数で指定した char 型の配列に格納された文字列をコピーすることができます。

strcpy
#include <string.h>

char *strcpy(char *, const char *);
MEMO

もっと正確にいうと、strcpy 関数では、第1引数で指定したアドレスに、第2引数で指定したアドレスから NULL 文字までのデータコピーします

ですので、数値をソートするプログラムでデータを代入で格納している部分を、文字列をソートするために strcpy 関数でデータを格納するように変更する必要があります。

例えば数値のソートプログラムでは、ソートを実行する selectionSort の下記で2つのデータの交換を行なっています。データは int 型なので、単なる代入を用いています。

数値をソートする場合のデータの格納
/* ソート範囲の先頭と最小値を交換 */
tmp = data[start];
data[start] = data[i_min];
data[i_min] = tmp;

一方で、文字列のソートプログラムでは、同様の処理を行う部分では下記のように strcpy 関数を利用してデータの格納を行うようにしています。

文字列をソートする場合のデータの格納
/* ソート範囲の先頭と最小値を交換 */
strcpy(tmp, data[start]);
strcpy(data[start], data[i_min]);
strcpy(data[i_min], tmp);

1つ注意点があって、その注意点とは「strcpy の第1引数と第2引数には同じアドレスを指定してはいけない」ことです。

例えば starti_min が同じ値であったとしても、下記の代入処理は問題なく実行することが可能です(ただし、元々の値と同じ値が格納されることになるので意味はないです)。

同じ要素に対する代入
data[start] = data[i_min];

一方で、starti_min が同じ値である場合、下記の strcpy 関数を実行するとエラー(プログラムが落ちる)になります(datachar 型の2次元配列)。

同じ要素に対するstrcpy
strcpy(data[start], data[i_min]);

strcpy では第1引数と第2引数に同じアドレスを指定することは禁止されています。

ですので、単に代入を strcpy 関数に置き換えるとプログラムが動作しなくなる可能性があるので注意してください。同じアドレスになるような場合は、strcpy 関数を実行しないようにする制御を追加する必要があります。

例えば文字列のソートプログラムでは下記のように同じアドレスに対する strcpy 関数が実行されないように if 文で制御するようにしています。

同じアドレスへのstrcpyをしないようにする制御
if (start != i_min) {

    /* ソート範囲の先頭と最小値を交換 */
    strcpy(tmp, data[start]);
    strcpy(data[start], data[i_min]);
    strcpy(data[i_min], tmp);
}

まとめ

このページでは、「文字列をソートするプログラム」の作り方の解説を行いました!

いきなり「文字列をソートするプログラム」を作るのは難易度が高いため、まずは数値をソートするプログラムを作成し、そこから文字列をソートするプログラムに仕立てていく方法を取ることをオススメします。

そして、この「数値をソートするプログラム」を「文字列をソートするプログラム」に仕立てるために必要な変更は大きくいうと下記の3つになります。

  • データを char 型の配列に格納するようにする
  • 大小関係の比較は strcmp 関数で行う
  • 代入は strcpy 関数に置き換える

「文字列をソートするプログラム」の元になる「数値をソートするプログラム」の作り方は下記のリンク先で紹介していますので、是非こちらも読んでみてください!

選択ソート解説ページのアイキャッチ選択ソートを図を使って分かりやすく解説(C言語サンプルプログラム付き) クイックソート解説ページのアイキャッチクイックソートを図を使って分かりやすく解説(C言語サンプルプログラム付き) マージソート解説ページのアイキャッチマージソートを図を使って分かりやすく解説(C言語サンプルプログラム付き) 挿入ソートの解説ページアイキャッチ挿入ソートを図を使って分かりやすく解説(C言語サンプルプログラム付き) ヒープソートの解説ページアイキャッチヒープソートを図を使って分かりやすく解説(C言語サンプルプログラム付き)

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です