qsort関数の理解と実装(およびバブリング分析)

私は最近qsortを学び、理解と記憶を深めるためにそれを書き留めました。
qsort関数を使用するには、ライブラリ関数<stdlib.h>が必要です。qsortをすばやく並べ替えて、選択内容を昇順または降順で確認できます。
例を見て、それがどうなるか見てみましょう。
qsortを使用する

#include <stdio.h>
#include <stdlib.h>
int cmp(const void* e1, const void* e2)
{
    
    
    return *(int*)e1 - *(int*)e2;
}

int main(void)
{
    
    
    //struct stu s[3] = { {10,"tom"},{40,"jack"},{20,"tim"} };
    int num[9] = {
    
    3,25,6,3,4,7,8,1,2 };
    int sz = sizeof(num) / sizeof(num[0]);
    qsort(num, sz, sizeof(num[0]), cmp);
    for (int i = 0; i < sz ; i++)
        printf("%d ",num[i]);
    return 0;
}
qsort(
      void* arr,
      size_t num,
      size_t width,
      int (*cmp)(const void* element1,const void* element2)
      )

qsort(配列の最初の要素、配列要素の数、各要素のバイトサイズ、比較関数ポインター)

上記と同様に、cmp関数ポインタを呼び出して、降順か昇順かを確認する必要があります。
cmpはqsortで呼び出す必要があります。e1-e2が昇順の場合、e2-e1は降順です。ねえ、なぜ見下ろしたのか、最初は戸惑いました。qsortがどのように機能するかを理解する必要があります。

ボイド*

これを紹介するために、それは初心者には比較的なじみのないはずです。ポインターを渡すときにタイプがわからないので、これを使用してすべてのタイプのポインターを受け取り、使用する必要があるときにそれらを目的のタイプに強制することができます。このような

return * (int)e1-* (int)e2;

qsort関数を実装する

#include <stdio.h>
#include <string.h> 
void swap(char* a, char* b, int width)
{
    
    
    for (int i = 0; i < width; i++)
    {
    
    
        char tmp = *a;
        *a = *b;
        *b = tmp;
        a++;
        b++;
    }
}

int cmp(void* e1, void* e2)
{
    
    
    return *(char*)e2 - *(char*)e1;
}
void my_sort(void* arr, int sz, int width, int (*cmp)(void* e1,void* e2))
{
    
    
    for (int i = 0; i < sz - 1; i++)
    {
    
    
        for (int j = 0; j < sz - i - 1; j++)
        {
    
    
        

if(cmp( (char* )arr+j*width,(char* )arr+(j+1)*width)>0)
            swap((char*)arr + j * width, (char*)arr + (j + 1) * width, width);
        }
    }
}
int main(void)
{
    
    
    int arr[] = {
    
     5,3,2,1,5,7,5,3,9,19 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    my_sort(arr, sz, sizeof(arr[0]), cmp);
    for (int i = 0; i < sz; i++)
        printf("%d ", arr[i]);
    return 0;
}

別の写真を見てくださいここに画像の説明を挿入

int cmp(void* e1, void* e2)
{
    
    
    return *(int*)e1 - *(int*)e2;
}

my_sortの呼び出しはqsortです。
このコード文字列は、ライターではなくユーザーが記述します。強制されるe1とe2のタイプは、ユーザーによって異なります。次に、my_sort関数の準備があります。結局、循環ソートです。バブリング、選択、挿入の種類がたくさんあります。これにはバブリングを使用します。実際、違いは大きくありません。主にソート用です。実際、次のことも可能です。文字列を並べ替えますが、見下ろすとわかります。最初の文字だけが並べ替えられます。もう一度分析させてください

バブルソート
番号2の列、3、4、1、与え
9、6、7、8及び
左またはアレイの右から比較するのバランスを取ります。タイトル通り、左からスタートします。
比較するたびに条件が交換され(条件は昇順か降順かによって異なります)、天びんは次の要素と比較するために1つの範囲を右に移動します。、ずっと下の比較で、この状況を取ります。昇順で、最大値は常に右端に移動します。信じないで、自分で試してみてください。降順の場合、最小値が右端に移動します。この個人は、ある程度の知識がある限り、過剰に研究されています。右端が取られていることがわかります。次のラウンドはまだ左端から始まります。ただし、1つ少ないものと比較することができます。
外側のループ条件はsz-1であり、これは最大ループsz-1回を表します。
…………たとえば、2つの要素が並べ替えられた場合、パスは1つだけです。この例えのように、3つの要素と2つのパスは、理解しにくいものです。
-内側のループは、毎回の比較と交換を解決する役割を果たします。同時に、条件もsz-1-iです。これは、各サイクルで1つを配置できるためです。たとえば、最初の行の8要素を7回比較し、2回目の行の7要素を6回比較します
…………なぜなら、右側は毎回ソート要件(昇順または降順)を満たすように配置できるからです。

ここに画像の説明を挿入
さて、泡立ちは終わりました、それはトピックに戻る時間です。

if(cmp( (char* )arr+j*width,(char* )arr+(j+1)*width)>0)
                swap((char*)arr + j * width, (char*)arr + (j + 1) * width, width);

ループするたびに、それを比較して、交換されているかどうかを確認する必要があります。次に、cmp関数に入り、上のステップ図を参照してください。戻り値がゼロより大きい場合は、ifを入力して交換を開始します

場合は
、E1-E2(フロントマイナスバック)が昇順であり、
E2-E1(前回マイナス前)は降順である
、それは簡単に理解することはだ、私はそれを説明することはできません。

判定条件が満たされると、スワップ機能が開始され、交換が開始されます。しかし、ライターは交換する要素のタイプを知りません。バイトごとにしか交換できませんが、直接どのくらいかわからないため、要素の幅幅も渡します。とても思いやりがあります。


文字列の場合文字は交換のために1バイトに格納されます。
数字であり、そうですが、通常の直接交換として理解でき、違いはありません。

交換後、次のバイトに移動して交換を続行します。
任意の構造にすることができます。
さて、それだけでいいのですが、考えてみたらもっと追加します。
すべてvs2019を使用してコンパイルします。
ご不明な点がございましたら、アドバイスをお願いいたします。
見てくれてありがとう。

おすすめ

転載: blog.csdn.net/weixin_52199109/article/details/112094686