C语言sort()函数的使用 详细介绍

qsort()函数(quick sort)是快速排序算法,可以排序任意数据类型的数组其中就包括整形,浮点型,字符串甚至自定义的结构体类型。

下图是4个参数的含义

 qsort(void *__base, size_t __nel, size_t __width,int (* _Nonnull __compar)(const void *, const void *));

1. void*base     (首元素地址)

我们要排序一个数组,首先要知道从哪儿开始排序,所以先把首元素地址传给qsort函数。 

2.size_t nell     (元素个数)

我们还要知道数组从哪里结束,但是由于排序的不确定性我们不清楚最后的元素地址,所以将元素个数传入qsort函数。

3.size_t width  (元素字节大小)

我们知道qsort函数可以排序任意类型的一组数据,因此我们采用void*类型的指针接收元素,但是void*类型的指针不能进行加减操作,也就无法移动。

那么在函数内部又是怎样操作变量的呢?

我们可以将void*类型的指针强制类型转换char*类型的指针后来操作元素。因为char*类型的指针移动一次的单位是一个字节,因此得知要操作的元素字节大小时,就可以让char*类型的指针移动该个字节到下一个元素,指针就可以指向那个元素了。

4.int (* _Nonnull __compar)(const void *, const void *))(比较函数)

我们要怎么给一组数据排序呢?例如可以给整形数据从小到大,也可以给浮点型数据从大到小,或者还可以比较字符串的大小也可以比较字符串的长度。这些我们就必须要写一个比较函数了。

具体的使用

要使用qsort函数我们要引用一个头文件<stdlib.h>

#include <stdlib.h>

比如我们要排序一个整形元素的数组


#include <stdio.h>
#include <stdlib.h>

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

int main()
{
    int arr[5] = {5, 2, 1, 4, 3};
    qsort(arr, 5, sizeof(arr[0]), compar);
    for (int i = 0; i < 5; i++){
        printf("%d ", arr[i]);
    }
    return 0;
}

打印出来的结果:

可以看到升序排列,而改变成降序排列只需要改变compar里的内容即可。


#include <stdio.h>
#include <stdlib.h>

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

int main()
{
    int arr[5] = {5, 2, 1, 4, 3};
    qsort(arr, 5, sizeof(arr[0]), compar);
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

可见,将return的值加上负号就能改变排列顺序,那么究竟是什么原因呢?接下来,我为大家用冒泡排序的方法实现这个函数。

#include <stdio.h>
#include <stdlib.h>

//交换函数的实现
void Swap(char *buf1, char *buf2, int width){
    while (width)
    {
        char box = *buf1;
        *buf1 = *buf2;
        *buf2 = box;
        buf1++;
        buf2++;
        width--;
    }
}

//比较函数的实现
int cmp(const void *e1, const void *e2){
    return *(int *)e1 - *(int *)e2;
}

void bubble_sort(void *base, int sz, int width, int (*cmp)(const void *, const void *)){
    int i, j = 0;
    for (i = 1; i < sz; i++){
        for (j = 0; j < sz - i; j++){
            // 调用cmp函数,这里可以规定函数排序的方式(升序or降序)
            if (cmp((char *)base + j * width, (char *)base + (j + 1) * width) > 0){
                // 满足上述条件,开始排序
                Swap((char *)base + j * width, (char *)base + (j + 1) * width, width);
            }
        }
    }
}

int main()
{
    int arr[5] = {4, 3, 1, 2, 5};
    int sz = sizeof(arr) / sizeof(arr[0]);
    bubble_sort(arr, sz, sizeof(arr[0]), cmp);
    for(int i=0; i<5; i++){
        printf("%d ",arr[i]);
    }
    return 0;
}

 所以根据上述函数的内部实现可以得出return的数值如果大于0,那么就进行交换并且实现排序。那么如果想要反方向排序的话,只需要让return的数值取负值,及前一个数比后一个数小就交换,及降序排序。

各种类型的cmp函数实现(除了整型,上面已包含)

1.浮点型

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

2.比较字符串大小

int cmp(const void *e1, const void *e2){
    return strcmp((char*)e1,(char*)e2);
}

3.比较字符的长度

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

4.比较结构体变量

int cmp(const void *e1, const void *e2){
    return (int)(((stu*)e1)->weight - ((stu*)e2)->weight);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值