【C语言】qsort函数的使用与模拟实现

引入

qsort函数:

qsort函数是C语言stdlib.h头文件中所包含的库函数,原型是void qsort(void*base,size_t num,size_t width,int(__cdecl*compare)(const void*,const void*));使用该函数,可以做到对一些数据进行排序,比如给没有顺序的数字排序,那么,他的优势在哪里呢?我们学过冒泡排序,知道使用他可以简易的排列数据,qsort函数与冒泡排序有什么不同?我列出了一些qsort的优点供大家参考

现成的,可以排序任意类型的数据

比较两个整数的大小,< > =

比较两个字符串,strcmp

比较两个结构体数据 指定比较的标准

接下来,让我们来看看这个函数的使用方法

使用

首先我们来看看qsort函数的参数设置

void qsort (

void* base,//要排序的对象

size_t num,//要排序的元素个数

size_t width,//宽度,即一个元素的大小,单位为字节

int(*cmp)(const void* e1, const void* e2)//qsort函数的使用者提供这个函数

);

其中后面的cmp是函数指针,它所表达的含义是指向一个函数并引用,也就是说,对数据排序的函数需要我们自己编译。

void* - 无具体类型的指针,所以他可以接受任何类型的地址,不能直接解引用操作,我们发现,比如冒泡排序的方法是无法排列字符型变量或结构体类型的变量,因为他们的类型不同,不适用于冒泡排序,但是在qsort函数中定义,我们可以传入任意类型的数据,也就是说他可以接受任何int,char,float等类型的变量,这就给了我们能排序任何类型的数据的“通行证”。

//冒泡排序
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;
            }
        }
    }
}

在了解了qsort函数的参数定义后,我们来实现一下排列数据的代码

要使用qsort来排序整型数组,就要提供一个比较函数,这个比较函数能够比较2个整数的大小,因此我们定义一个简单的比较函数

int cmp_int(const void* p1, const void* p2)
{
    return *(int*)p1 - *(int*)p2;
}

完成后,我们可以再定义一个函数,用来定义要排序的数组和存放qsort和打印函数。

void test1()
{
    int arr[] = { 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);
    print(arr,sz);
}
void print(int arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);//循环打印
    }
    printf("\n");
}

再用main函数调用就完成了

int main()
{
    test1();
    return 0;
}

是不是很简单?让我们运行试试

【C语言】qsort函数的使用与模拟实现_第1张图片

那我们再试试排列结构体类型?

也很简单,让我们先定义一个结构体变量

struct Stu
{
    char name[20];
    int age;
};
//接着,进行同样的操作:定义一个比较函数,这里拿年龄举例
int cmp_stu_by_age(const void* p1, const void* p2)
{
    return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}

接着定义函数使用qsort

void test2()
{
    struct Stu s[] = { {"zhangsan",20},{"lisi",25},{"wangwu",50} };
    int sz = sizeof(s) / sizeof(s[0]);
    qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}
int main()
{
    test2();
    return 0;
}

运行后发现可以排序

模拟实现

在知道qsort函数的定义和如何使用后,我们是否可以用冒泡排序来模拟实现qsort的功能?答案是肯定的,虽然在前面我们提到冒泡排序不能排列全部类型的数据,但是我们可以再定义一个函数swap,希望这个bubble_sort可以排序任意类型的数据,这样就可以达到目的,接着,我们再接受数据进行遍历排序,这个模拟qsort函数就实现了

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++;
    }
}
//size_t是无符号整型,num是个数,个数不能是负数,width是宽度,即数据元素的字节大小
void bubble_sort(void* base,size_t num,size_t width,int (*cmp)(const void* p1,const void* p2))
{
    size_t i = 0;
    for (i = 0; i < num - 1; i++)
    {
        int flag = 1;//假设有序
        //一趟排序的过程
        size_t j = 0;
        for (j = 0; j < num - 1; j++)
        {
            if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
            {
                //转换为char类型,char*指针加一跳过一个字节
                //j*width 跳过j*width个字节,width是宽度,相当于跳过j个元素
                //int*跳过四个字节,不能判断结构体和char类型
                flag = 0;
                Swap((char*)base + j * width, (char*)base + (j + 1) * width,width);
            }
        }
        if (flag == 1)
        {
            break;
        }
    }
}
void test3()
{
    int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
    print(arr, sz);
}

void test4()
{
    struct Stu s[] = { {"zhangsan",20},{"lisi",25},{"wangwu",50} };
    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()
{
    test3();
    test4();
    return 0;
}

你可能感兴趣的:(萌新,c语言,学习)