C语言qsort函数

本文详细介绍了C语言中的qsort函数,包括其参数含义和使用方法,以及如何自定义比较函数。此外,还通过冒泡排序算法模拟了qsort函数的工作原理,帮助读者更深入理解排序过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

qsort函数使用

再C语言stdlib.h库中,提供了一个用来排序的函数。

这个函数就是qsort函数,qsort函数的返回值是void类型,有四个参数。qsort函数排序完成后,默认是升序的。

void qsort(void*x, size_t num, size_t size, int (*P)(const void* p1, const void* p2));

第一个参数是排序的起始位置,第二个是需要排序的元素个数,第三个是元素的字节长度,第四个是用来判断大小的函数。

第四个参数是回调函数,这个函数是需要使用者自己提供的,也就是当我们使用qsort函数时,还需要自己写一个判断函数。设计这个函数时,函数的返回类型是int,两个参数都是void*类型的地址,在使用使用这两个地址时,需要进行强制类型转换,因为void*类型的是无法直接使用的,用const修饰是因为我们只是两个地址的两个元素,并不改变,使函数的安全性变高。


#include <stdio.h>
#include <stdlib.h>
int cam_int(const void* p1, const void* p2)
{
    return *(int*)p1 - *(int*)p2;
}
int main()
{
    int arr[] = { 5,2,6,4,7,9,4,1,3 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    qsort(arr, sz, sizeof(arr[0]), cam_int);
    for (int i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

在上面的cam_int函数内我们我们在使用两个地址时需要先一步进行强制类型转换。这样才能正常使用两个地址。

我们还可以用qsort函数来排序字符串

只需要重新写一个cam_char函数就行。


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int cam_char(const void* p1, const void* p2)
{
    return *(char*)p1 - *(char*)p2;
}
int main()
{
    char arr[] = "dbaksfh";
    qsort(arr, strlen(arr), sizeof(arr[0]), cam_char);
    printf("%s", arr);
    return 0;
}

也可以用来排序结构体。


#include <stdio.h>
#include <string.h>
#include<stdlib.h>
struct stu {
    char name[20];
    int age;
};
int cam_stu_name(const void* p1, const void* p2)
{
    return strcmp((*(struct stu*)p1).name, (*(struct stu*)p2).name);
}
int cam_stu_age(const void* p1, const void* p2)
{
    return (*(struct stu*)p1).age - (*(struct stu*)p2).age;
}
int main()
{
    struct stu s[3] = { {"wang",18}, {"lishi",24}, {"zhag",14} };
    qsort(s, sizeof(s) / sizeof(s[0]), sizeof(s[0]), cam_stu_name);
    for (int i = 0; i < sizeof(s) / sizeof(s[0]); i++)
    {
        printf("{%s %d} ",s[i].name,s[i].age);
    }
    printf("\n");
    qsort(s, sizeof(s) / sizeof(s[0]), sizeof(s[0]), cam_stu_age);
    for (int i = 0; i < sizeof(s) / sizeof(s[0]); i++)
    {
        printf("{%s %d} ", s[i].name, s[i].age);
    }
    return 0;
}

接下来我们更加深入了解qsort函数,qsort函数使用的排序方法使快排,我们则用冒泡排序来代替快排,实现一个冒泡排序的qsort函数。

冒泡排序

冒泡排序就是将第一个元素与第二个元素比较,当前面的元素小于后面的元素是时,就将它们两个交换,然后重复上面的操作,将第二个元素与第三个元素比较。当完成这样一次循环后,最后一个元素就是最大的那个。然后再次循环,这次要比较的元素就少一个,就是最后一个,因为最后一个已经排好了。每次循环都排好一个元素。


#include <stdio.h>
int main()
{
    int arr[10] = { 3,4,7,8,4,2,1,5,9,8 };
    int i = 0;
    int j = 0;
    for (i = 0; i < 10; i++)
    {
        for (j = 0; j < 10 - i - 1; j++)
        {
            if(arr[j]>arr[j+1])
                {
                    int x = arr[j];
                    arr[j]=arr[j+1];
                    arr[j + 1] = x;
                }
        }
    }
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

模拟qsort函数

上面我们实现了冒泡排序,接下来我们模拟实现qsort函数。

首先分析qsort函数组成。

void qsort(void*arr, size_t num, size_t size, int (*p)(const void*p1,const void* p2))。

就像上面说的一样,第一个参数设计成void*是为了接收所有类型的地址。

那现在我们需要知道第二和第三个参数有什么用。

其实可以推测出来,第二和第三个参数的作用就是将元素的地址传给第四个参数。

知道num我们就知道了要比较多少个元素,知道了size我们就知道每个元素的地址之间相差几个字节。

当我们想寻找第二个元素是就可以通过(char*)arr+size这个地址来访问。这里要记得强制类型转换char*,因为void*不能直接使用并且char*类型就是一个字节,加size就是跳过几个字节。


#include <stdio.h>
bubble_sort(void*arr,size_t num,size_t size,int (*p)(const void*p1,const void*p2))
{
    int i = 0;
    int j = 0;
    for (i = 0; i < num; i++)
    {
        for (j = 0; j < 10 - i - 1; j++)
        {
            int x = (*p)((char*)arr + j * size, (char*)arr + (j + 1) * size);
            if (x > 0)
            {
                char w = *((char*)arr + j * size);
                *((char*)arr + j * size) = *((char*)arr + (j + 1) * size);
                *((char*)arr + (j + 1) * size) = w;
            }
        }
    }
}
int cam_int(const void* p1, const void* p2)
{
    return *(int*)p1 - *(int*)p2;
}

int main()
{
    int arr[10] = { 4,7,2,5,6,9,0,1,4,3 };
    bubble_sort(arr, 19, sizeof(arr[0]), cam_int);
    for (int i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

这样一个使用冒泡排序写的qsort函数就完成了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值