C言語 - 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. バブルソートを使うアイデア
  2. あらゆるタイプのデータ並べ替えに適用可能
    問題 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;
}

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/plj521/article/details/131819291