执行排序的 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 > s) - (f < s);
好的,根据大多数建议进行了更改。我在需要 size_t 时画了一条线,@ChrisL,因为我的数组从来没有变得那么大:-) 而且,@AndreyT,虽然这个技巧很聪明,但我更喜欢我的代码可读:-)
@paxdiablo:“hack”是一个成熟的成语。任何称职的程序员都会立即认识到这一点。它对可读性没有负面影响。
@JAamish ISO C99 标准 N1256,在“7.20.5.2 qsort
函数”第 4 点“如果两个元素比较相等,则它们在结果排序数组中的顺序未指定。”【参考方案2】:
C/C++ 标准库<stdlib.h>
包含qsort
函数。
这不是世界上最好的快速排序实现,但它足够快而且非常 易于使用... qsort 的正式语法是:
qsort(<arrayname>,<size>,sizeof(<elementsize>),compare_function);
您唯一需要实现的是 compare_function,它包含两个 “const void”类型的参数,可以转换为适当的数据结构,然后 返回以下三个值之一:
否定,如果 a 应该在 b 之前 0,如果 a 等于 b 肯定的,如果 a 应该在 b 之后1.比较整数列表:
只需将 a 和 b 转换为整数
如果x < y
,x-y
为负,x == y
,x-y = 0
,x > 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。比较字符串列表:
为了比较字符串,你需要 <string.h>
库中的 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 > y) return +1; else if (x < y) return -1; else return 0;
,或者如果你想要一个简单的表达式,那么return (x > y) - (x < 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】:在<stdlib.h>
中使用qsort()
。
@paxdiablo
qsort()
函数符合 ISO/IEC 9899:1990 (``ISO C90'')。
【讨论】:
【参考方案7】:我认为您正在寻找qsort
。qsort
函数是在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 库函数的主要内容,如果未能解决你的问题,请参考以下文章