stdlib.h中qsort函数的使用

自从学会了用qsortqsortqsort排序之后,再也没有在程序里自己写排序了。
第一次还觉得这个函数怎么用起来这么复杂,还得自己编写比较函数,现在可不这么觉得了,觉得好用的一批,这个比较函数简直是神器。那么下面就来介绍下qsortqsortqsort函数的使用吧,关键就是 比较函数 的编写。


函数原型:

void qsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *));

1、普通简单形式元素:

typedef int TYPE;
int cmp(const void* A, const void* B)
{
    	return *(TYPE*)A - *(TYPE*)B;
}
TYPE nodes[] = {2, 9, 2, 5, 14, 8, 20};
int n = sizeof(nodes)/sizeof(*nodes);
qsort(nodes, n, sizeof(*nodes), cmp);

排序后原数组变为2, 2, 5, 8, 9, 14, 20。这里的TYPE是intintint型,当然也可以换成charcharchar, floatfloatfloat, doubledoubledouble等类型,道理一样不再赘述。

2、二维数组中一维数组:

这句话的意思好像怎么看都有点歧义的感觉,那就举个例子来说明吧:

现在有个二维数组,每一行都存储了一个字符串,现在要对这个二维数组中的字符串进行排序,排序之后这个二维数组的每一行的字符串变成有序。比较函数可以这么写:

int cmp(const void* A, const void* B)
{
    return strcmp((char*)A, (char*)B);
}

现在令二维数组为:

char nodes[4][10] = {"Hello", "world!", "C", "program"};

其长度为:

int n = sizeof(nodes)/sizeof(*nodes);

随后排序:

qsort(nodes, n, sizeof(*nodes), cmp);

二维数组中的字符串变为升序:

C
Hello
program
world!

3、结构体元素排序

令结构体为:

typedef struct NODE
{
    int a;
    char str[10];
}Node;
  • 如果结构体要针对其中的子元素aaa进行排序,比较函数可以写为:
int cmp(const void* A, const void* B)
{
    return (*(Node*)A).a - (*(Node*)B).a;
}

这里一定要注意括号!因为.的优先级比*
或者用->一样的,依然要注意括号

int cmp(const void* A, const void* B)
{
    return ((Node*)A)->a - ((Node*)B)->a;
}
  • 如果对结构体的strstrstr 进行排序,比较函数可写为:
int cmp(const void* A, const void* B)
{
    return strcmp((*(Node*)A).str, (*(Node*)B).str)
}

基本的用法也就这样了,如果仅仅是进行以上的简单排序,那么自己写个排序函数好像也没啥难度,不一定非要用qsortqsortqsort。而当比较情况变复杂的时候,qsortqsortqsort函数的优势就体现出来了,这也是它真正吸引我的地方。举个例子吧:

仓库管理员小闻最近进了一批钢管,这批钢管应该按照老板的指示来排放,可是老板的要求有点苛刻:
1.首先按照钢管的编号降序排序
2.编号一样时,按照钢管直径长度升序排序
3.钢管直径也一样,那么按照长度降序排序
这下子可把小闻难坏了,?坑爹的老板。你来帮帮小闻把这批钢管排序吧!

typedef struct STEEL
{
    int num;
    int diameter;
    int lenth;
}Steel;
int cmp(const void* a, const void* b)
{
    if((*(Steel*)a).num != (*(stell*)b).num)
        return (*(Steel*)b).num - (*(stell*)a).num;//按照序号降序排序
    if((*(Steel*)a).diameter != (*(stell*)b).diameter)
        return (*(Steel*)a).diameter - (*(stell*)b).diameter;//按照直径升序排序
    if((*(Steel*)a).lenth != (*(stell*)b).lenth)
        return (*(Steel*)b).lenth - (*(stell*)a).lenth;//按照长度降序排序
    return 0;
}
Steel steel[n];
qsort(steel, n, sizeof(*steel), cmp);

假如现在有5个数据:

1 2 3
1 1 5
3 2 1
3 2 3
5 1 1

那么,经排序后,得到:

5 1 1
3 2 3
3 2 1
1 1 5
1 2 3

确实是序号降序,直径升序,长度降序排序。

补充:指针数组的排序

现在有一个指针数组: p={"Where there is hope ,there is a way","Welcome Beijing","Nice idea","Have fun"},对这个数组进行排序,比较函数写为:

int cmp(const void* A, const void* B)
{
    return strcmp(*(char**)A, *(char**)B);
}

再更:结构体指针数组的排序

2019.2.4

typedef struct NODE{
    int num;
    struct NODE* next;
}Node;

int cmp(const void* A, const void* B){
    return (*(Node**)A)->num - (*(Node**)B)->num;
}

void sort(Node* head){
    int top = 0;
    int lenth = getLength(head);
    Node* buff[lenth];
    //目的是将这个链表的所有节点的地址存放起来,然后对这个数组中的指针排序。
    //在gdb中调试,可以看到buff的类型为: (Node *(*)[0])
    Node* p = head->next;
    while(p){
        buff[top++] = p;
        p = p->next;
    }
    qsort(buff, lenth, sizeof(*buff), cmp);

    p = head;
    for(int i = 0; i < lenth; i++){
        p->next = buff[i];
        p = p->next;
    }
    p->next = NULL;

}


文末祝大家学习愉快^_^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值