【问题标题】:Sorting an array in C?在C中对数组进行排序?
【发布时间】:2011-04-23 01:51:27
【问题描述】:

以下数组排序的最佳排序技术是什么,如果有重复如何处理它们:

int a= {1,3,6,7,1,2};

还有哪一种是最好的排序技术?

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;
            }
        }
    }
}

【问题讨论】:

  • 没有“最好的排序技术”,这取决于数据的大小以及是否在一开始就进行了排序。我建议您阅读en.wikipedia.org/wiki/… 以及整篇维基百科文章。
  • "best" 取决于数据和其他限制:内存、速度、如何开始排序错误。快速排序是其中的一个很好的折衷方案。冒泡排序最适合小内存。你想完成什么?
  • 最好的(如果最好 == 最快的)排序技术是获取已经排序的数据。
  • "后面的数组" = "前面的数组"?如果是的话,最快的就是把它写下来排序。说真的,我在生成的代码中这样做。

标签: c algorithm sorting


【解决方案1】:

在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 )

见:http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/


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

附带说明一下,如果您对自己的数据有所了解,有时可以比 O(n log(n)) 做得更好 - 请参阅Radix Sort 上的维基百科文章

【讨论】:

  • @Alex:如果你想要它快,至少提供一个像样的比较功能! qsort 不需要返回值是-1、0、1,而是“任何负数”、0、“任何正数”,因此您只需执行return *((int*)a)-*((int*)b);,这比您的建议要快得多。跨度>
  • @kriss:在整数溢出的情况下,您的比较没有明确定义;因此,人们经常会看到类似return (a &gt; b) - (a &lt; b)
  • @Stephen Canon:同意,当您对数据范围一无所知并且可能发生溢出时,您应该使用 Christoph 之类的公式。在实际情况下,我在处理有符号数字时从未见过一次,但我对数据范围没有一些粗略的了解(而且我的公式也适用于无符号数)。我的观点主要是比较 API 结果类型不是 -1,0,1(或者我们甚至不能使用 strcmp 来比较 char*)。
  • @kriss:这种符号的使用是完全错误的。即使它是随机的,它可以遇到需要二次时间的情况。因此,大 O 是二次的。大 O 总是表示最坏情况。对荒谬的“平均案例”复杂度估计使用不同的符号。
  • @kriss:如果我说一个算法在时间上是O(f(n)),这意味着它运行的时间f(n)的恒定倍数为界,其中对于所有可能的输入,特定的常量依赖于实现,但在实现中是常量。声称快速排序是 O(n log n) 就像声称 if (rand()==42) return find_prime_factors(n); else return NULL;O(1) 相对于 n 一样荒谬。
【解决方案2】:

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

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

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

为了对大量数据进行排序,算法还必须处理与磁盘之间的数据交换,这是在数据库中实现的排序类型,如果您有这样的需求,最好的选择是将数据放入某个数据库中并使用内置排序。

【讨论】:

    【解决方案3】:

    视情况而定

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

    基础知识

    要了解哪种算法效果最好,您需要了解algorithms complexitybig-O notation 的基本知识,以便了解它们如何根据average case, best case and worst case scenarios 进行评分。如果需要,您还必须关注sorting algorithm's stability

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

    查看以下内容,了解使用分而治之方法的“高级搜索”:

    这些更简单的算法适用于不太复杂的算法:

    进一步

    以上是入门时常见的嫌疑人,但还有无数其他的。

    正如 R. 在 cmets 和 kriss 在他的回答中指出的那样,您可能想看看 HeapSort,它在理论上提供了比快速排序更好的排序复杂性(但通常不会更好在实际设置中)。还有变体和hybrid algorithms(例如TimSort)。

    【讨论】:

    • 如果你提供一个完全倒置的列表来进行快速排序,它只会在最简单的实现中退化(总是将列表的头部作为枢轴),即使那样它也不会比 BubbleSort 更糟。天真的快速排序对于已经排序的列表也会表现不佳。但是对算法进行非常简单的更改就足以避免该问题(从列表中提取几个数字作为潜在枢轴并选择中位数作为枢轴)。
    • @kriss:正确。但这是一个 CS 学习问题,所以我只讨论每种方法的理论和基本实现。显然,您可以调整算法并最大限度地减少这些副作用,但是当 OP 询问一般排序问题时,我认为确定这些问题更符合要求。
    • @haylem:这确实可能是一个学习问题,但谈论幼稚实现的风险是让读者相信库调用 qsort 是 QuickSort 的幼稚实现,它不是,并且会在已排序的数据集上退化。如果我没记错的话,在大多数实现中它甚至不是快速排序。
    • 您遗漏了堆排序,这可以说是理想的排序(O(1) 空间和O(n log n) 时间)。
    • @R.:我猜我漏掉了很多 :) 但你说得对,我应该提到堆排序。
    【解决方案4】:

    我想做一些改变: 在 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 )
    

    【讨论】:

      【解决方案5】:

      最好的排序技术通常取决于数组的大小。合并排序可能是最好的,因为它根据 Big-O 算法管理更好的空间和时间复杂度(这更适合大型数组)。

      【讨论】:

        猜你喜欢
        • 2013-12-24
        • 2013-08-05
        • 2021-11-18
        • 1970-01-01
        • 2018-04-20
        • 2012-04-25
        • 2011-04-25
        • 1970-01-01
        相关资源
        最近更新 更多