执行排序的 C 库函数

Posted

技术标签:

【中文标题】执行排序的 C 库函数【英文标题】:C library function to perform sort 【发布时间】:2010-12-19 18:26:27 【问题描述】:

C 标准库中是否有可用的库函数来进行排序?

【问题讨论】:

@Alexandru,SO 的全部意义在于成为所有任何技能水平的编程相关问题的地方。当人们使用您的查询时,您认为 Google 应该将他们引导到哪里?希望它出现在here的权力 - 当 SO 是该查询的*** Google 链接时,我们的工作就完成了。 我的原始代码很懒惰,可能与您通过 Google 搜索找到的代码大不相同。然而,在所有社区输入之后,您就有了一个如何使用 qsort 的良好实现示例。 @paxdiablo:如果是这样的话,他们还不如简单地托管标准的 lib 文档——我怀疑这个问题会在规范参考之上添加任何内容,这里。对于一些复杂的情况,也许 - 但只是为了找到一个基本功能? 即使是这样的问题也有助于 SO 的最终完整性,作为对卡住的编码人员有用的数据库。 在很多情况下人们也不知道要搜索什么。如果您知道 c 有一个名为 qsort() 的排序函数,那么文档很容易访问,但是如果您不知道应该使用什么资源。 【参考方案1】:

qsort() 是您正在寻找的功能。您可以使用指向数据数组的指针、该数组中的元素数量、每个元素的大小和一个比较函数来调用它。

它发挥了它的魔力,您的数组就地排序。下面是一个例子:

#include <stdio.h>
#include <stdlib.h>
int comp (const void * elem1, const void * elem2) 

    int f = *((int*)elem1);
    int s = *((int*)elem2);
    if (f > s) return  1;
    if (f < s) return -1;
    return 0;

int main(int argc, char* argv[]) 

    int x[] = 4,5,2,3,1,0,9,8,6,7;

    qsort (x, sizeof(x)/sizeof(*x), sizeof(*x), comp);

    for (int i = 0 ; i < 10 ; i++)
        printf ("%d ", x[i]);

    return 0;

【讨论】:

您真的应该使用 sizeof(*x) 以防您将来更改类型,但 +1 以提供样本。 在一般情况下,尝试通过将整数相减来比较整数会导致溢出。最好从一开始就远离那个坏习惯。使用return (f &gt; s) - (f &lt; s); 好的,根据大多数建议进行了更改。我在需要 size_t 时画了一条线,@ChrisL,因为我的数组从来没有变得那么大:-) 而且,@AndreyT,虽然这个技巧很聪明,但我更喜欢我的代码可读:-) @paxdiablo:“hack”是一个成熟的成语。任何称职的程序员都会立即认识到这一点。它对可读性没有负面影响。 @JAamish ISO C99 标准 N1256,在“7.20.5.2 qsort 函数”第 4 点“如果两个元素比较相等,则它们在结果排序数组中的顺序未指定。”【参考方案2】:

C/C++ 标准库&lt;stdlib.h&gt; 包含qsort 函数。

这不是世界上最好的快速排序实现,但它足够快而且非常 易于使用... qsort 的正式语法是:

qsort(<arrayname>,<size>,sizeof(<elementsize>),compare_function);

您唯一需要实现的是 compare_function,它包含两个 “const void”类型的参数,可以转换为适当的数据结构,然后 返回以下三个值之一:

否定,如果 a 应该在 b 之前 0,如果 a 等于 b 肯定的,如果 a 应该在 b 之后

1.比较整数列表

只需将 a 和 b 转换为整数 如果x &lt; y,x-y 为负,x == y,x-y = 0,x &gt; y,x-y 为正 x-y 是一种捷径:) 将*x - *y 反转为*y - *x,用于按降序/倒序排序

int compare_function(const void *a,const void *b) 
int *x = (int *) a;
int *y = (int *) b;
return *x - *y;

2。比较字符串列表:

为了比较字符串,你需要 &lt;string.h&gt; 库中的 strcmp 函数。 strcmp 默认情况下会适当地返回 -ve,0,ve... 以相反的顺序排序,只需反转 strcmp 返回的符号

#include <string.h>
int compare_function(const void *a,const void *b) 
return (strcmp((char *)a,(char *)b));

3.比较浮点数

int compare_function(const void *a,const void *b) 
double *x = (double *) a;
double *y = (double *) b;
// return *x - *y; // this is WRONG...
if (*x < *y) return -1;
else if (*x > *y) return 1; return 0;

4.根据键比较记录

有时您需要对更复杂的东西进行排序,例如记录。这里是最简单的 使用qsort 库的方法。

typedef struct 
int key;
double value;
 the_record;

int compare_function(const void *a,const void *b) 
the_record *x = (the_record *) a;
the_record *y = (the_record *) b;
return x->key - y->key;

【讨论】:

一个很好的答案,但是比较函数的返回值的解释是倒退的。此外,在某些示例中,您正在使用 x-y 技巧,这可能会给出错误的结果(并且比简单的比较不那么明显)。 好吧,就我现在而言..这适用于每场比赛;) 如果 x 和 y 之间的差大于最大可表示的 int,则 x-y 技巧不起作用。所以比较两个正数是可以的,但是比较会失败,例如INT_MAX和-10。赞成,因为我喜欢所有分类不同类型的例子。 以及整数比较器和键比较器函数中的溢出问题,字符串比较函数不正确。在对int 的数组进行排序时,传递给比较器的值都是int * 伪装成void *。因此,在对char * 的数组进行排序时,传递给比较器的值都是char ** 伪装成void *。因此,正确的代码需要是:int compare_function(const void *a,const void *b) return (strcmp(*(char **)a, *(char **)b)); . 对于抗溢出的整数比较,考虑if (x &gt; y) return +1; else if (x &lt; y) return -1; else return 0;,或者如果你想要一个简单的表达式,那么return (x &gt; y) - (x &lt; y);。这总是在 C 级别评估两个比较,但优化器可能能够避免这种情况。减法不适用于无符号值。第一个版本在您处理一系列比较时效果很好 - 首先比较结构的 2 个整数成员,如果它们相等,然后是两个双精度数,然后是两个字符串,等等。有不止一种方法可以做到,在 C 和 Perl 中。【参考方案3】:

当然:qsort() 是一种排序的实现(不一定是它的名字所暗示的快速排序)。

试试 man 3 qsort 或阅读http://linux.die.net/man/3/qsort

【讨论】:

qsort 不必使用快速排序来实现。【参考方案4】:

虽然不完全在标准库中,https://github.com/swenson/sort 只有两个头文件,您可以包含这些头文件来访问各种令人难以置信的快速排序路由,如下所示:

#define SORT_NAME int64
#define SORT_TYPE int64_t
#define SORT_CMP(x, y) ((x) - (y))
#include “排序.h”
/* 您现在可以访问 int64_quick_sort、int64_tim_sort 等,例如 */
int64_quick_sort(arr, 128); /* 假设你有一些 int *arr 或 int arr[128]; */

这应该至少比标准库qsort 快两倍,因为它不使用函数指针,并且有许多其他排序算法可供选择。

它在 C89 中,所以基本上可以在每个 C 编译器中工作。

【讨论】:

【参考方案5】:

在 stdlib.h 中尝试qsort

【讨论】:

【参考方案6】:

&lt;stdlib.h&gt; 中使用qsort()

@paxdiablo qsort() 函数符合 ISO/IEC 9899:1990 (``ISO C90'')。

【讨论】:

【参考方案7】:

我认为您正在寻找qsortqsort 函数是在stdlib.h 中的C/C++ 中找到的快速排序算法的实现。

下面是调用qsort函数的语法:

void qsort(void *base, size_t nmemb, size_t size,int (*compar)(const void *, const void *));

参数列表:base:指向数组第一个元素或基地址的指针nmemb:数组中的元素数 size:每个元素的字节大小 compar:比较两个元素的函数元素

这是一个使用qsort 对数组进行排序的代码示例:

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

int arr[] =  33, 12, 6, 2, 76 ;

// compare function, compares two elements
int compare (const void * num1, const void * num2) 
   if(*(int*)num1 > *(int*)num2)
    return 1;
   else
    return -1;


int main () 
   int i;

   printf("Before sorting the array: \n");
   for( i = 0 ; i < 5; i++ ) 
      printf("%d ", arr[i]);
   
   // calling qsort
   qsort(arr, 5, sizeof(int), compare);

   printf("\nAfter sorting the array: \n");
   for( i = 0 ; i < 5; i++ )    
      printf("%d ", arr[i]);
   
  
   return 0;

您可以在 Linux/Mac 终端输入man 3 qsort 以获取有关qsort 的详细信息。Link to qsort man page

【讨论】:

【参考方案8】:

stdlib.h 中有几个可用的 C 排序函数。您可以在 unix 机器上执行 man 3 qsort 以获取它们的列表,但它们包括:

堆排序 快速排序 合并排序

【讨论】:

堆排序和合并排序不在标准中。 快速排序也不是。该标准没有规定使用哪种算法。

以上是关于执行排序的 C 库函数的主要内容,如果未能解决你的问题,请参考以下文章

C语言标准库函数qsort详解

c语言重要库函数解读 和模拟实现————Qsort

c++的algorithm库常用函数

C 库函数 ------ qsort()

linux 下的动态库制作 以及在python 中如何调用 c 函数库

静态函数库的制作和使用