C阵列排序技巧

Raj*_*eev 28 c sorting algorithm

int a= {1,3,6,7,1,2};
Run Code Online (Sandbox Code Playgroud)

哪种是对以下数组进行排序的最佳排序技术,如果存在重复,则如何处理它们.也是最好的分拣技术....

void BubbleSort(int a[], int array_size)
{
    int i, j, temp;
    for (i = 0; i < (array_size - 1); ++i)
    {
        for (j = 0; j < array_size - 1 - i; ++j )
        {
            if (a[j] > a[j+1])
            {
                temp = a[j+1];
                a[j+1] = a[j];
                a[j] = temp;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Ale*_*ece 44

在C中,您可以使用内置qsort命令:

int compare( const void* a, const void* b)
{
     int int_a = * ( (int*) a );
     int int_b = * ( (int*) b );

     if ( int_a == int_b ) return 0;
     else if ( int_a < int_b ) return -1;
     else return 1;
}

qsort( a, 6, sizeof(int), compare )
Run Code Online (Sandbox Code Playgroud)

请参阅:http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/


要回答问题的第二部分:最佳(基于比较)排序算法是使用O(n log(n))比较运行的算法.有几个具有此属性(包括快速排序,合并排序,堆排序等),但使用哪个取决于您的用例.

作为旁注,如果您对数据有所了解,有时可以比O(n log(n))更好 - 请参阅有关Radix Sort的维基百科文章

  • @kriss:在整数溢出的情况下,你的比较没有明确定义; 因此,人们经常会看到像`return(a> b) - (a <b)`这样的东西 (6认同)
  • @Alex:如果你想要它快,至少提供一个体面的比较功能!qsort不需要返回的值为-1,0,1,但是"任何负数",0,"任何正数",因此你只需要做`return*((int*)a) - *( (int*)b);`这比你的提议快得多. (4认同)
  • @Stephen Canon:同意,当您对数据范围一无所知并且可能发生溢出时,您应该使用像 Christoph 那样的公式。在实际情况中,在处理有符号数字时,我从未见过任何一次发生,因为我对数据范围没有一些粗略的了解(而且我的公式对于无符号数也很好)。我的观点主要是比较 API 结果类型不是 -1,0,1 (或者我们甚至无法使用 strcmp 来比较 char*)。 (2认同)
  • @kriss:这种符号的使用是完全错误的.即使它是随机的,它也可以**遇到需要二次时间的情况.因此,**大O是二次**.大O**总是**意味着**最坏情况**.对于荒谬的"平均情况"复杂性估计使用不同的符号. (2认同)
  • @kriss:如果我说算法的时间是"O(f(n))",那就意味着它运行的时间是由{f(n)`**的常数倍所限定的,其中特定的对于所有可能的输入**,常量是依赖于实现但在实现中是恒定的.声称快速排序是"O(n log n)"与声称`if(rand()== 42)返回find_prime_factors(n)一样荒谬; else返回NULL;`相对于`n`是`O(1)`. (2认同)
  • @kriss:平均是**绝对无关的**。Big O 是一个边界问题,与平均表现无关。我的“rand()”示例是,很容易编写一个平均性能很快但最坏情况任意慢的函数。正如 Alex 所指出的,显然可以制作一种在“O(n log n)”时间内运行的快速排序变体,但您对大 O 术语的使用仍然不正确。 (2认同)

kri*_*iss 12

在您的特定情况下,最快的排序可能是本答案中描述的排序.它针对6个整数的数组进行了精确优化,并使用了排序网络.它比库qsort快20倍(在x86上测量).排序网络对于某种固定长度的阵列是最佳的.由于它们是固定的指令序列,因此甚至可以通过硬件轻松实现.

一般来说,有一些针对某些特殊情况优化的排序算法.堆排序或快速排序等通用算法已针对项目数组的就地排序进行了优化.它们产生O(n.log(n))的复杂度,n是要排序的项目数.

库函数qsort()在复杂性方面编码非常好并且有效,但是使用了对用户提供的某些比较函数的调用,并且该调用具有相当高的成本.

对于排序非常大量的数据算法也需要处理数据与磁盘的交换,这是在数据库中实现的那种排序,如果你有这样的需求,最好的办法是将数据放入某个数据库并使用内置排序.


hay*_*lem 5

要看

这取决于各种各样的事情.但是一般来说,使用Divide-and-Conquer/dichotomic方法的算法在排序问题时表现良好,因为它们呈现出有趣的平均情况复杂性.

基本

要了解哪种算法效果最好,您需要具备算法复杂度大O符号的基本知识,因此您可以了解它们在平均情况,最佳情况和最差情况方面的评分.如果需要,您还必须注意排序算法的稳定性.

例如,通常一种有效的算法是快速排序.但是,如果你给quicksort一个完美的倒置列表,那么它的表现会很差(在这种情况下,简单的选择排序会表现得更好!).如果对列表进行预分析,Shell-sort通常也是quicksort的一个很好的补充.

对于使用分而治之的方法进行"高级搜索",请查看以下内容:

对于不太复杂的算法,这些更直接的算法:

进一步

上面是开始时常见的嫌疑人,但也有无数其他人.

正如R.在评论中和kriss在他的回答中指出的那样,你可能想看看HeapSort,它提供了理论上比快速排序更好的排序复杂性(但在实际环境中通常不会更好).还有变体和混合算法(例如TimSort).


小智 5

我想进行一些更改:在 C 中,您可以使用内置的qsort命令:

int compare( const void* a, const void* b)
{
   int int_a = * ( (int*) a );
   int int_b = * ( (int*) b );

   // an easy expression for comparing
   return (int_a > int_b) - (int_a < int_b);
}

qsort( a, 6, sizeof(int), compare )
Run Code Online (Sandbox Code Playgroud)