千家信息网

C语言中如何使用qsort函数

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,小编给大家分享一下C语言中如何使用qsort函数,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一.qsort函数是什么我们
千家信息网最后更新 2026年11月01日C语言中如何使用qsort函数

小编给大家分享一下C语言中如何使用qsort函数,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

    一.qsort函数是什么

    我们可以使用 搜索库函数网址或者MSDN软件进行查找。

    qsort()函数:快速排序的函数 -引用stdlib.h头文件

    参数说明:

    void qsort (     void* base, //要排序的目标数组    size_t num,     //待排序的元素个数    size_t width,    //一个元素的大小,单位是字节    int(*cmp)(const void* e1, const void* e2));

    其中cmp是函数指针,cmp指向的是:排序时,用来比较两个元素的函数。需要自己编写。

    返回值:

    二.使用qsort排序-以升序为例

    关于void*型指针:

    void*:无具体类型的指针 能够接收任意类型的地址
    缺点:不能进行运算。不能+-整数,不能解引用

    int a  = 0;float f = 5.5f;void* p1 = &a;void* p2 = &f;p1 = p1+1;    //err

    1.整形数组排序

    注意:

    1.比较函数的参数类型为void* ,我们要进行强制类型转换!且要解引用才能得到对应的值!

    2.若我们想排成降序,只需要写成e2-e1即可

    void Print(int* arr, int sz){        int i = 0;        for (i = 0; i < sz; i++)        {                printf("%d ", *(arr + i));        }        printf("\n");}//比较整形//注意类型时void* 所以要强制类型转化,还要解引用才是对应的值!!!int cmp_int(const void* e1, const void* e2){        return *(int*)e1 - *(int*)e2;}void test1(){        int arr[] = { 9,8,7,6,7,5,4,8 };        int sz = sizeof(arr) / sizeof(arr[0]);        qsort(arr, sz, sizeof(arr[0]), cmp_int);        Print(arr, sz);}

    2.字符数组排序

    注意使用sizeof()操作符和strlen()函数的区别

    //注意要要强制类型转换!! 要解引用!!!  本质上是比较Ascii值int cmp_char(const void* e1, const void* e2){    return *(char*)e1 - *(char*)e2;}void test4(){        char arr[] ="mango";    //若使用sizeof计算长度:        //int sz = sizeof(arr) / sizeof(arr[0]);       //6        //qsort(arr, sz-1, sizeof(arr[0]), cmp_float);    //因为sizeof把\0也算进去了,所以计算出来的值比字符串本身长度多1        int sz = strlen(arr);    //5    qsort(arr, sz, sizeof(arr[0]), cmp_char);        printf("%s\n",arr);}

    3.字符指针数组排序

    先看看下面这段程序有没有问题?

    int cmp_chars(const void* e1, const void* e2){        return strcmp((char*)e1, *(char*)e2);}void test2(){         char* arr1 = "abc";         char* arr2 = "wcad";         char* arr3 = "cab";         char* p[3] = { arr1,arr2,arr3 };        int sz = sizeof(p) / sizeof(p[0]);        qsort(p, sz, sizeof(p[0]), cmp_chars);        int i = 0;        for (i = 0; i < sz; i++)        {                printf("%s\n", p[i]);        }}

    打印出来发现:结果是错误的!

    ->调试后发现:e2存放的是p的地址(char**类型),e1存放的是p指向的下一个元素的地址(char**类型)

    对于这种写法,传进去的是p的地址,strcmp()会将p地址对应的内容转化成字符串,也就是将p中arr1,arr2,arr3的地址转化成字符串

    实际上应该传p地址空间中arr1,arr2的地址,这样strcmp()才能找到arr1和arr2对应的字符串,因此得先把e1,e2转化成char**,这样解引用以后才是一个char*的地址

    原因:把p传给qsort,p是数组名->首元素地址,元素类型为char*>,所以p的类型为:char**类型。 所以e1 和e2也要强制类型转化为char**,解引用e1,e2才是对应字符串的地址!

    正解:

    int cmp_chars(const void* e1, const void* e2){        return strcmp(*(char**)e1, *(char**)e2);}void test2(){         char* arr1 = "abc";         char* arr2 = "wcad";         char* arr3 = "cab";         char* p[3] = { arr1,arr2,arr3 };        int sz = sizeof(p) / sizeof(p[0]);        qsort(p, sz, sizeof(p[0]), cmp_chars);        int i = 0;        for (i = 0; i < sz; i++)        {                printf("%s\n", p[i]);        }

    4.结构体数组排序

    比较年龄->实际比较的是整形

    比较名字->实际比较的是字符串->使用strcmp函数,不能使用 == 判断

    struct Stu{        int age;        char name[20];};//比较结构体中元素的年龄int cmp_age(const void* e1, const void* e2){        //本质是比较整形        return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;}//比较名字int cmp_name(const void* e1, const void* e2){        //本质是字符串比较->使用strcmp函数        return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);}void test2(){        //创建结构体数组,用大括号初始化        struct Stu s[3] = { {19,"Mango"},{18,"Lemon"},{20,"Hello"} };        int sz = sizeof(s) / sizeof(s[0]);        //以年龄排        qsort(s, sz, sizeof(s[0]), cmp_age);        printf("%s %d ",s[0].name,s[0].age);        printf("%s %d ", s[1].name, s[1].age);        printf("%s %d ", s[2].name, s[2].age);        printf("\n");        //以姓名排        qsort(s, sz, sizeof(s[0]), cmp_name);        printf("%s %d ", s[0].name, s[0].age);        printf("%s %d ", s[1].name, s[1].age);        printf("%s %d ", s[2].name, s[2].age);        printf("\n");}

    5.浮点型数组排序

    注意:比较函数中,返回类型是int,最后相减的值要强制类型转化为int ,但这也会造成错误,建议使用方法2.

    //写法1:可能会出错// 原因: 0.2 -0.1 = 0.1 强制类型转化为int后 结果为0//int cmp_float(const void* e1, const void* e2)//{//      //返回类型是int  所以相减后的结果要强制类型转化//      return (int)(*(float*)e1 - *(float*)e2);//} //写法2:对应上qsort的返回值int cmp_float(const void* e1, const void* e2){        if ((*(float*)e1 - *(float*)e2) > 0.00000)                return 1;        else if ((*(float*)e1 - *(float*)e2) == 0.000000)                return 0;        else                return -1;}void test3(){        float arr[5] = { 5.01f,5.01f,0.02f,0.01f,5.001f };        int sz = sizeof(arr) / sizeof(arr[0]);        qsort(arr, sz, sizeof(arr[0]), cmp_float);        int i = 0;        for (i = 0; i < sz; i++)        {                printf("%f ", arr[i]);        }}

    三.使用冒泡排序思想模拟实现qsort函数

    1.什么是冒泡排序:

    主要思想:相邻的两个元素进行比较

    对于冒泡排序: n个元素 共进行n-1趟冒泡排序。一趟可以使一个元素在特定位置上,每趟排序可以少比较一个元素

    但是冒泡排序只能排序整形

    2.冒泡排序代码

    void BubbleSort(int* arr, int sz){        int i = 0;        int j = 0;        int flag = 1;//假设一开始有序        //共进行sz-1趟        for (i = 0; i < sz-1; i++)        {                // 每一趟                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;                                flag = 0;                        }                }                if (flag == 1)                {                        break;                }        }}int main(){        int arr[10] = { 2,3,6,7,9,0,0,3,2,10 };        int sz = sizeof(arr) / sizeof(arr[0]);        BubbleSort(arr, sz);        return 0;}

    3. 使用冒泡排序思想模拟实现qsort函数

    qsort库函数使用的是什么参数,我们设计的函数就使用什么参数!

    1.为何将base强制类型转化为char*型指针:

    原因:char* 指针+1跳过一个字节,+width:跳过width个字节,指向下一个元素。转化为其他类型不合适

    2. 交换函数:还要把宽度(每个元素所占字节数)传过去
    因为交换的时候是传地址,所以要知道元素的宽度,一个字节一个字节的交换 ,这样也证明了使用char*指针的好处!

    3.(char*)base + j * width, (char*)base + (j + 1) * width,

    当j = 0时:比较的是第一个元素和第二个元素
    j = 1时,比较的是第二个元素和第三个元素
    .... 很妙的写法

    //交换 --一个字节一个字节的交换,共交换width次void Swap(char* buf1, char* buf2, size_t width){        size_t i = 0;        for (i = 0; i < width; i++)        {                char tmp = *buf1;                *buf1 = *buf2;                *buf2 = tmp;                buf1++;                buf2++;        }}void my_BubbleSort(void* base, size_t num,size_t width, int(*cmp)(const void* e1, const void* e2)){        //冒泡排序        //若要排序n个元素,只需要进行n-1趟        //每一趟可以少比较一个元素,每一趟可以使一个元素在确定的位置上        //num:要排序元素的个数 类型是size_t     //num是无符号数 防止产生警告 所以i和j也定义为size_t    // size_t == unsigned int         size_t i = 0;        size_t j = 0;         //共进行num-1趟        for (i = 0; i < num; i++)        {                //每一趟                for (j = 0; j < num - 1 - i; j++)                {                        //比较                        //传地址                           //相邻两个元素比较   width:宽度,每个元素所占字节                        //排成升序                        if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)                        {                                //交换两数                                Swap( (char*)base + j * width, (char*)base + (j + 1) * width, width );                        }                }        }}

    当然 ,交换也可以使用库函数memcpy

    dest:目标空间

    src:要拷贝到目标空间的字符 -因为不作修改,所以可以用const修饰

    count:字节数

    char tmp [30];    //防止结构体类型之类的类型    临时空间memcpy(tmp, (char*)base + j * size, size); memcpy( (char*)base + j * size,  (char*)base + (j + 1) * size, size);memcpy( (char*)base + (j + 1) * size, tmp, size);

    以上是"C语言中如何使用qsort函数"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

    类型 元素 排序 函数 地址 字符 字节 数组 强制 字符串 指针 写法 参数 空间 结构 内容 原因 实际 年龄 思想 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 广州大一互联网络科技有限公司 喔噻互联网科技 上海挚品互联网科技 奇酷互联网科技 互联网未来科技 华中科技大学互联网 齐家互联网科技有限公司 重庆科技学院互联网 衡水科技产业互联网平台 上海电发互联网科技有限公司 科技与互联网的利与弊 中国科技互联网公司收入 温州喔噻互联网科技有限公司 广州慧亚互联网科技怎么样 北京华百购互联网科技有限公司 搜狐科技互联网 互联网方面的科技前沿 从那以后互联网科技有限公司 银川新华互联网科技学校是国营吗 现代科技的标志之一的互联网 中关村互联网科技集团 互联网科技巨头监管 科技平台互联网 广州互联网络科技有限公司 哈尔滨新华互联网科技 花神(南京)互联网科技有限公司 银川新华互联网科技学校联系电话 翼展科技 首家互联网医院 威龙国际互联网科技公司 广州梦谷互联网科技有限公司领导
    0