qsort関数の詳しい説明
序文:
qsort() 関数 (クイック ソート) は、8 つのソート アルゴリズムの中のクイック ソートであり、整数、浮動小数点型、文字列、さらにはカスタム構造型を含むあらゆるデータ型の配列をソートできます。
1. qsort関数の意味
Web サイトをクリックします: https://cplusplus.com/reference/——> クリックして古いバージョンの関数ハイパーリンク インターフェイスを表示します (関数の意味を表示します)
古いバージョン
クエリする関数をフィールドに入力しますqsort関数
の意味を表示する検索ボックス
1.1 関数パラメータ
//void qsort(void* base,//指向了需要排序的数组的第一个元素
// siez_t num, //排序的元素个数
// size_t size, //一个元素类型的大小,单位是字节。
// int (*compar)(const void*, const void*))//函数指针类型——这个函数指针指向的函数能够比较base指向数组中的两个元素。
この関数には 4 つのパラメータがあります: 最初のパラメータはポインタ、size_t は符号なし整数 (2 番目と 3 番目のパラメータ)、4 番目のパラメータは関数ポインタの型です。
Base が指す num 個の要素を並べ替えます。各要素は size バイトの長さを持ち、この comper が指す関数を使用して順序 (比較順序) を検出します。
1.2 パラメータの意味
base:base は、ソートされる配列の最初の要素を指し、void* に変換されます。
num: 符号なし整数である、base が指す配列空間内の要素の数。
size: 各要素の単位はバイト数であり、符号なしの整数です。
comper: 2 つの要素を比較する関数 int comper(const void* p1, const void* p2) を指すポインタ
;
2 つの関数を比較し、p1 が指す値と p2 が指す
値を比較します。 p1 が p2 が指す値より大きい場合は、0 を超える数値を返します。p1
が指す値が p2 が指す値と等しい場合は、0 に等しい数値を返します。p1 が指す値が 0 である場合は、0 に等しい数値を返します
。 p2 が指す値より小さい場合は、<0 の数値を返します。
2. さまざまな種類のデータを使用して sqort をテストする
2.1 配列内の整数をソートする
整数の昇順:
#include <stdio.h>
#include <stdlib.h>
int comper(const void* p1, const void* p2)
{
return (*(int*)p1 - *(int*)p2);
}
int main()
{
int arr1[10] = {
3,6,8,2,6,9,1,5,8,4 };
qsort(arr1,sizeof(arr1)/sizeof(arr1[0]),sizeof(int),comper);
int i = 0;
for (i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++)
printf("%d ", arr1[i]);
return 0;
}
2.2 配列内の浮動小数点数をソートする
#include <stdio.h>
#include <stdlib.h>
int comper(const void* p1, const void* p2)
{
return (*(float*)p1 - *(float*)p2);
}
int main()
{
float arr1[10] = {
3.33,6.66,8.88,2.22,6.66,9.99,1.11,5.55,8.88,4.44 };
qsort(arr1, sizeof(arr1) / sizeof(arr1[0]), sizeof(float), comper);
int i = 0;
for (i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++)
printf("%0.3f ", arr1[i]);
return 0;
}
2.3 文字列のソート
#include <stdio.h>
#include <stdlib.h>
int comper(const void* p1, const void* p2)
{
return (*(char*)p1 - *(char*)p2);
}
int main()
{
char arr1[10] = "asdfghjkl";
qsort(arr1, sizeof(arr1) / sizeof(arr1[0]), sizeof(char), comper);
int i = 0;
for (i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++)
printf("%c ", arr1[i]);
return 0;
}
2.4 構造の並べ替え
構造は文字サイズでソートされます
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct str
{
char arr[10];
int age;
};
int comper(const void* p1, const void* p2)
{
return strcmp(((struct str*)p1)->arr,((struct str*)p2)->arr);
}
int main()
{
struct str ar[3] = {
{
"pan",19},{
"wang",21},{
"li",31}};
qsort(ar, sizeof(ar) / sizeof(ar[0]), sizeof(ar[0]), comper);
int i = 0;
for (i = 0; i < sizeof(ar) / sizeof(ar[0]); i++)
printf("%s,%d\n", ar[i].arr, ar[i].age);
return 0;
}
3. qsort関数の実現をシミュレーションする
- バブルソートを使うアイデア
- あらゆるタイプのデータ並べ替えに適用可能
問題 1: パラメーターは整数配列のみを受け入れることができます
解決策 1: void* へのポインター
//void qsort(void* base,//指向了需要排序的数组的第一个元素
// siez_t num, //排序的元素个数
// size_t size, //一个元素类型的大小,单位是字节。
// int (*compar)(const void*, const void*))//函数指针类型——这个函数指针指向的函数能够比较base指向数组中的两个元素。
質問 2: 整数の比較サイズ < > ==
構造体の比較サイズ。比較するにはメンバーの型を確認する必要があります。
データの種類が異なる場合、単純に > を使用して比較することはできません。
解決策 2: 2 つの要素の比較メソッドを関数のパラメーターとして渡します。
int comp(const void* p1, const void* p2)
{
return (*(int*)p1 - *(int*)p2);
}
全体的な実装:
//模拟实现qsort函数
#include <stdio.h>
int comp(const void* p1, const void* p2)
{
return (*(int*)p1 - *(int*)p2);
}
void swap(void* p1, void* p2,int si)//元素arr[j]和元素arr[j+1]进行交换,si表示交换的字节大小
{
int i = 0;
for (i = 0; i < si; i++)//把每个字节进行交换,整体就进行交换了
{
char tmp = *((char*)p1 + i);
*((char*)p1 + i) = *((char*)p2 + i);
*((char*)p2 + i) =tmp ;
}
}
void qsort(char* base, int num, int si, int(*com)(const void* ,const void*))//
{
int i, j;
for(i=0;i<num-1;i++)
for (j = 0; j < num - i - 1; j++)
{
if (com((char*)base + si * j, (char*)base + (j + 1) * si) > 0)//由小到大排序,两元素比较大小,将arr[j]和arr[j+1]的地址传递给com函数
{
swap((char*)base + si * j, (char*)base + (j + 1) * si,si);//进行交换
}
}
}
int main()
{
int arr[15] = {
1,3,5,7,9,11,13,15,14,12,10,8,6,4,2 };//定义一个整型数组
int zs = sizeof(arr) / sizeof(arr[0]);
qsort(arr, zs, sizeof(int), comp);
int i;
for (i = 0; i < zs; i++)
printf("%d ", arr[i]);
return 0;
}