bilibiliclass33-35_C语言_指针的进阶_qsort库函数详解_冒泡排序升级(可以接受任意类型的数据)

冒泡排序

冒泡排序的原理

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。

  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

  3. 针对所有的元素重复以上的步骤,除了最后一个。

  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

 

回忆之前写过的冒泡排序
 

#include
void bubble_sort(int arr[], int sz)
{
    int i = 0;
    //趟数
    for (i = 0; i < sz - 1; i++)
    {
        //一趟冒泡排序
        int j = 0;
        for (j = 0; j < sz - 1 - i; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}

int main()
{
    int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
    int sz = sizeof(arr) / sizeof(arr[0]);

    bubble_sort(arr, sz);
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ",arr[i]);
    }
    return 0;
}

 

qsort-快速排序任意类型的数据

1.头文件stdlib.h
2.两个元素的比较方法不一样,需要使用者自己输入一个函数来比较两个数据

3.使用方法:

#include

int cmp_XXX (const void *e1,const void *e2)
{

//整形return *(int*)e1    -   *(int*)e1;
//浮点型return (int)(*(float*)e1    -   *(float*)e1);
//结构体return ((struct Stu*)e1)->指向结构体内部的元素-((struct Stu*)e2)->指向结构体内部的元素;
}

int sz=sizeo数组名(数组名)/sizeo数组名(数组名[0]);

qsort(      数组首元素的地址也就是数组名      ,        数组的元素个数sz           ,          单个元素的字节数sizeo数组名(数组名[0])          ,         使用者自己编写的函数cmp_XXX      );

 

函数原型
void qsort(void* base,//快速排序的目标,待排序数组的首元素的地址
                size_t num,//待排序数组的元素的个数
                size_t width,//待排序数组的单个元素的字节数
                int(*compare)(const void *e1,const void *e2)//比较两个目标的地址,相等返回0,小于返回负数,大于返回正数,
                //这个函数需要使用者自己实现
                );

void* 类型的指针

void* 类型的指针可以接受任意类型的地址
void* 类型的指针 不能进行解引用操作
void* 类型的指针 不能进行加减整数的操作
存储例如:void* p=&a;(a是任意类型的数据)

 


下面通过代码来体验一下qsort函数和自己编写的冒泡排序升级(可以接受任意类型的数据)

附有较为详细的注释

    test1();//qsort排序整形
    test2();//qsort排序浮点型
    test3();//qsort排序结构体
    test4();//冒泡排序整形
    test5();//冒泡排序结构体

 

#include
#include
#include
//比较整数数据
int cmp_int(const void* e1, const void* e2)
{
    //比较两个整形值的
    return *(int*)e1 - *(int*)e1;
}

void test1()
{
    int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    qsort(arr, sz, sizeof(arr[0]), cmp_int);

    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

//比较浮点型数据
int cmp_float(const void* e1, const void* e2)
{
    return (int)(*(float*)e1 - *(float*)e1);
}

void test2()
{
    float f[] = { 9.0,8.0,7.0,6.0,5.0,4.0,3.0,2.0,1.0 };
    int sz = sizeof(f) / sizeof(f[0]);

    qsort(f, sz, sizeof(f[0]), cmp_float);

    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%f\n", f[i]);
    }
}

//比较结构体型数据
struct Stu
{
    char name[20];
    int age;
};

int cmp_stu_by_age(const void* e1, const void* e2)
{
    return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}

int cmp_stu_by_name(const void* e1, const void* e2)
{
    //比较名字就是比较字符串,应该用strcmp函数,比较字符串的,头文件为string.h
    return strcmp(((struct Stu*)e1)->name , ((struct Stu*)e2)->name);
}

void test3()
{
    struct Stu s[3] = { {"zhangsan",20},{"lisi",30},{"wangwu",10} };
    int sz = sizeof(s) / sizeof(s[0]);
    qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
    qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}


// void qsort(void* base,//快速排序的目标,待排序数组的首元素的地址
                // size_t num,//待排序数组的元素的个数
                // size_t width,//待排序数组的单个元素的字节数
                // int(*compare)(const void *e1,const void *e2)//比较两个目标的地址,相等返回0,小于返回负数,大于返回正数,
                // //这个函数需要使用者自己实现
                // );


//改造冒泡排序
//实现bubble_sort的程序员,他不知道未来排序的数据类型
//那程序员也不知道,待比较两个元素的类型
void(Swap)(char* buf1, char* buf2, int width)
{
    int i = 0;
    for (i = 0; i < width; i++)
    {
        char tmp = *buf1;
        *buf1 = *buf2;
        *buf2 = tmp;
        buf1++;
        buf2++;
    }
}

void bubble_sort(void* base, int sz, int width, int (*cmp)(const void* e1, const void* e2))
{
    int i = 0;
    //趟数
    for (i = 0; i < sz - 1; i++)
    {
        //一趟冒泡排序
        int j = 0;
        for (j = 0; j < sz - 1 - i; j++)
        {
            //两个元素的比较
            //*void无法直接加减
            //(char*)将其强制转成字符指针可以加减,加减1跳过一个字节
            if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
            {
                //交换
                Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
            }
        }
    }
}


void test4()
{
    int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    //使用bubble_sort函数的程序员一定知道自己排序的是什么数据
    //就应该知道如何比较待比较的数据的方式
    bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
}

void test5()
{
    struct Stu s[3] = { {"zhangsan",20},{"lisi",30},{"wangwu",10} };
    int sz = sizeof(s) / sizeof(s[0]);
    bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_age);
    bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}

int main()
{
    test1();
    test2();
    test3();
    test4();
    test5();
    return 0;
}

 

你可能感兴趣的:(C语言_哔哩哔哩课堂笔记)