「C言語の基礎 - ソート関数」の版間の差分

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動
(Wiki がページ「ソート関数による並び替え」を「C言語の基礎 - ソート関数」に、リダイレクトを残さずに移動しました)
(文字列「source lang」を「syntaxhighlight lang」に置換)
4行目: 4行目:


== 定義の詳細 ==
== 定義の詳細 ==
  <source lang="c++">
  <syntaxhighlight lang="c++">
  #include <stdlib.h>
  #include <stdlib.h>
  void qsort(void *base, size_t num, size_t size, int (*compare)(const void *a, const void *b));
  void qsort(void *base, size_t num, size_t size, int (*compare)(const void *a, const void *b));
25行目: 25行目:
配列を昇順で整列する方法を下記に記述する。
配列を昇順で整列する方法を下記に記述する。
尚、asc関数は比較関数である。
尚、asc関数は比較関数である。
  <source lang="c++">
  <syntaxhighlight lang="c++">
  // int型の場合
  // int型の場合
  int asc(const void *a, const void *b)
  int asc(const void *a, const void *b)
41行目: 41行目:
  </source>
  </source>
<br>
<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  // long型の場合
  // long型の場合
  // long型の演算結果をそのまま比較関数の戻り値に使うと、int型のオーバーフローが発生し、正確な整列が行えなくなるため、注意すること
  // long型の演算結果をそのまま比較関数の戻り値に使うと、int型のオーバーフローが発生し、正確な整列が行えなくなるため、注意すること
62行目: 62行目:
  </source>
  </source>
<br>
<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  // 文字列の場合
  // 文字列の場合
  // strcmp関数の戻り値(負の値, 0, 正の値のいずれかを返す)を比較関数側の戻り値として活用するとよい。
  // strcmp関数の戻り値(負の値, 0, 正の値のいずれかを返す)を比較関数側の戻り値として活用するとよい。
80行目: 80行目:
  </source>
  </source>
<br>
<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  // 構造体の場合
  // 構造体の場合
  struct tag_PERSON
  struct tag_PERSON
106行目: 106行目:


==== 降順 ====
==== 降順 ====
  <source lang="c++">
  <syntaxhighlight lang="c++">
  // int型の場合
  // int型の場合
  int desc(const void *a, const void *b)
  int desc(const void *a, const void *b)
122行目: 122行目:
  </source>
  </source>
<br>
<br>
  <source lang="c++">
  <syntaxhighlight lang="c++">
  // 文字列の場合
  // 文字列の場合
  int compare_string(const void *a, const void *b)
  int compare_string(const void *a, const void *b)

2021年11月22日 (月) 15:23時点における版

qsort関数とは

qsort関数は、第1引数に指定された配列を、第4引数に指定された比較関数の規則に沿って並び替える。 第2引数には配列のサイズ、第3引数には配列要素のデータサイズを指定する。

定義の詳細

<syntaxhighlight lang="c++">
#include <stdlib.h>
void qsort(void *base, size_t num, size_t size, int (*compare)(const void *a, const void *b));
第1引数	base     ソート対象の配列
第2引数	num      配列要素の個数
第3引数	size     配列要素のサイズ
第4引数	compare  比較関数(コールバック関数)

// 比較関数
int (*compare)(const void *a, const void *b)
比較関数の状態         戻り値
第1引数の方が小さい	負の値
両方の引数が等しい	0
第1引数の方が大きい	正の値
</source>


qsort関数の使い方

昇順

配列を昇順で整列する方法を下記に記述する。 尚、asc関数は比較関数である。

<syntaxhighlight lang="c++">
// int型の場合
int asc(const void *a, const void *b)
{
   return *(int *)a - *(int *)b;
}

int main()
{
   int a[] = {2, 3, 1};
   qsort(a, sizeof(a) / sizeof(int), sizeof(int), asc);
   printf("%d, %d, %d", a[0], a[1], a[2]);
   // 表示結果 : "1, 2, 3"
}
</source>


<syntaxhighlight lang="c++">
// long型の場合
// long型の演算結果をそのまま比較関数の戻り値に使うと、int型のオーバーフローが発生し、正確な整列が行えなくなるため、注意すること
int asc(const void *a, const void *b)
{
   long *A = (long *)a;
   long *B = (long *)b;
   if (*A > *B) return 1;
   if (*A < *B) return -1;
   return 0;
}

int main()
{
   long a[] = {2, 3, 1};
   qsort(a, sizeof(a) / sizeof(long), sizeof(long), asc);
   printf("%d, %d, %d", a[0], a[1], a[2]);
   // 表示結果 : "1, 2, 3"
}
</source>


<syntaxhighlight lang="c++">
// 文字列の場合
// strcmp関数の戻り値(負の値, 0, 正の値のいずれかを返す)を比較関数側の戻り値として活用するとよい。

int compare_string(const void *a, const void *b)
{
   return strcmp(*(const char **)b, *(const char **)a);
}

int main()
{
   const char *names[] = {"Bob", "Ann", "Chris"};
   qsort(names, 3, sizeof *names, compare_string);
   printf("%s, %s, %s", names[0], names[1], names[2]);
   // 表示結果 : "Ann, Bob, Chris"
}
</source>


<syntaxhighlight lang="c++">
// 構造体の場合
struct tag_PERSON
{
   int person_id;
   const char *person_name;
}PERSON;

int compare_person_id(const void *a, const void *b)
{
   PERSON *A = (PERSON *)a;
   PERSON *B = (PERSON *)b;
   return A->person_id - B->person_id;
}

int main()
{
   PERSON Persons[] = {{2, "Bob"}, {3, "Ann"}, {1, "Chris"}};
   qsort(Persons, 3, sizeof(PERSON), compare_person_id);
   printf("%s, %s, %s", Persons[0].person_name, Persons[1].person_name, Persons[2].person_name);
   // 表示結果: "Chris,Bob,Ann"
}
</source>



降順

<syntaxhighlight lang="c++">
// int型の場合
int desc(const void *a, const void *b)
{
   return *(int *)b - *(int *)a;
}

int main()
{
   int a[] = {2, 3, 1};
   qsort(a, sizeof(a) / sizeof(*a), sizeof(*a), desc);
   printf("%d, %d, %d", a[0], a[1], a[2]);
   // 表示結果 : "3, 2, 1"
}
</source>


<syntaxhighlight lang="c++">
// 文字列の場合
int compare_string(const void *a, const void *b)
{
   return strcmp(*(const char **)a, *(const char **)b);
}

int main()
{
   const char *names[] = {"Bob", "Ann", "Chris"};
   qsort(names, 3, sizeof *names, compare_string);
   printf("%s, %s, %s", names[0], names[1], names[2]);
   // 表示結果 : "Chris, Bob, Ann"
}
</source>