Qsort 及其相关问题

Posted

技术标签:

【中文标题】Qsort 及其相关问题【英文标题】:Qsort and issues with it 【发布时间】:2013-04-03 05:29:36 【问题描述】:

以下是我的代码,Qsort 产生奇怪的结果:

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

char values[] =  0x02,0x04,0x0b,0x16,0x24,0x30,0x48,0x6c;

int compare (const void * a, const void * b)

    return ( *(int*)a - *(int*)b );


int main ()


    int i;

    qsort (values, 8, sizeof(char), compare);

    for (i = 0; i < 8; i++)
    
       printf ("%0x ",values[ i ]);
    
    return 0;

这个程序的输出是:

2 6c 48 30 24 4 b 16

虽然它应该与输入相同。有人可以解释一下为什么会这样以及我该如何纠正吗?

【问题讨论】:

我不敢相信。一个完全独立、可编译的示例!先生,您应该为此获得勋章! +1,如果可以的话,还有更多。 好点子,@DevSolar,我们应该奖励这样的问题。 【参考方案1】:
return ( *(int*)a - *(int*)b );

如果底层“对象”是char 值,则您应该比较int 值。

几乎可以肯定的是,比较使用四个(取决于sizeof(int))字节进行比较,例如第一个对象是0x02040b16(当然取决于您的字节序)。这会极大地阻塞进程。

改成:

return ( *(char*)a - *(char*)b );

然后再试一次。

请注意char 的签名是一个实现问题。您可能会发现0x80 最终小于0x7f。如果这不是您想要的,请显式使用unsigned char提取这些值,然后在进行减法之前将它们升级为有符号整数(使用另一个强制转换)。

事实上,为了可移植性,您可能还想在其他情况下明确使用signed char

以下程序显示了它如何使用正确的基础数据类型:

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

signed char values[] = 0x02, 0x04, 0x0b, 0x16, 0x24, 0x30, 0x6c, 0x48;

int compare (const void *a, const void *b) 
    return *(signed char*)a - *(signed char*)b;


int main (void) 
    int i;

    qsort (values, 8, sizeof (char), compare); // char okay here.
    for (i = 0; i < 8; i++)
       printf ("%0x ", values[i]);
    putchar ('\n');

    return 0;

这个输出是:

2 4 b 16 24 30 48 6c

(我交换了代码中最后两个元素的顺序,以表明它实际上是在排序)。

【讨论】:

"这会极大地阻塞进程。" -- 是的......在排序过程中,被排序的值实际上会发生变化! 如果 OP 对无符号字符进行排序,return *(unsigned char *)a - *(unsigned char *) b 是否会出错,因为减法永远不会产生否定结果? 好点@Adrian,修改文本以说明它们应该在减法之前升级为signed int。虽然,即使在那里,你也可能会遇到奇怪的架构问题,这些架构对于 char 和 int 具有相同的大小(不太可能)。 @paxdiablo compare 返回一个 int,所以 return *(unsigned char *)a - *(unsigned char *) 会产生负结果,因为它被计算为 int。【参考方案2】:

将比较功能更改为

int compare (const void * a, const void * b)

    return ( *(char*)a - *(char*)b );

【讨论】:

以上是关于Qsort 及其相关问题的主要内容,如果未能解决你的问题,请参考以下文章

用冒泡排序模拟实现qsort函数

qsort 在 C++ 中不适用于哪些类型?

qsort_b 和 qsort

关于 qsort 实现的问题

qsort 使用啥排序算法?

模板小程序链表排序(qsort/insert_sort/merge_sort)