Algorithm 为什么不';我们不能在链表上使用快速排序吗?

Algorithm 为什么不';我们不能在链表上使用快速排序吗?,algorithm,sorting,time-complexity,Algorithm,Sorting,Time Complexity,快速排序算法可分为以下步骤 1) 识别枢轴 2) 基于pivot对链表进行分区 3) 将链表递归地分成两部分 现在,若我总是选择最后一个元素作为轴心,那个么识别轴心元素(第一步)需要O(n)个时间 在确定pivot元素之后,我们可以存储它的数据并将其与所有其他元素进行比较,以确定正确的分区点(第二步)。当我们存储数据透视时,每次比较需要O(1)时间,每次交换需要O(1)时间。因此,对于n个元素,总共需要O(n)个时间 所以递归关系是 T(n)=2T(n/2)+n是O(nlogn),与链表合并排序

快速排序算法可分为以下步骤

1) 识别枢轴

2) 基于pivot对链表进行分区

3) 将链表递归地分成两部分

现在,若我总是选择最后一个元素作为轴心,那个么识别轴心元素(第一步)需要O(n)个时间

在确定pivot元素之后,我们可以存储它的数据并将其与所有其他元素进行比较,以确定正确的分区点(第二步)。当我们存储数据透视时,每次比较需要O(1)时间,每次交换需要O(1)时间。因此,对于n个元素,总共需要O(n)个时间

所以递归关系是

T(n)=2T(n/2)+n是O(nlogn),与链表合并排序相同

那么,对于链表,为什么合并排序优于快速排序呢

所以递推关系是。。。O(非登录)

数组上最坏的情况是O(n^2),例如,每个递归级别只会将最大分区的大小减少1或2(如果两个分区中都不包含pivot,则为2)

那么,对于链表,为什么合并排序优于快速排序呢

它的速度要快得多,尤其是自底向上的合并排序,它消除了对列表进行扫描以拆分列表。相反,它使用一个小型(26到32个)内部数组指针或节点引用(或小型列表数组),将节点合并到数组中,然后合并数组以创建排序列表。Wiki文章包括伪代码:

现在,如果我总是选择最后一个元素作为轴,那么 元素(第一步)需要O(n)时间

它实际上需要O(1)个时间。但无论如何,一个常见的误解是w.r.t.quick sort认为您可以选择一个预定义的元素作为轴心,而不是随机的。你可能不会

快速排序平均在O(N log(N))中工作,但最坏的情况是O(N^2)。现在,当枢轴被随机选择,算法在大集合上执行时——那么实际上O(nLog(N))就是你在实践中得到的结果。但是,如果您选择了一个预定义的轴心,那么,根据数据的模式,您很容易遇到最坏的情况。 认为源数据是而不是随机的,它来自某个源,并且呈现出某种模式

例如,如果您以最后一个元素为轴心,并且您的“以防万一”源数据已按相反顺序排序,那么您肯定会得到退化的O(N^2)


关于为什么链接列表通常不使用快速排序的问题。原因(IMHO)是,对于列表,合并排序是首选方式。它保证了O(N log(N))的最坏情况性能。它通常不用于数组,因为对于数组,它需要分配额外的内存,但链表的情况并非如此。

链表首选合并排序-需要引用。我投票将此问题作为离题题结束,因为这更适合该网站。@tadman那么我不允许在这里问算法和时间复杂性问题吗?在这个网站上有很多这样的问题。由于没有提供引文,我自己查阅了它,并且指出链表的缓慢随机访问性能使得其他一些算法(如quicksort)性能很差,而其他算法(如heapsort)完全不可能。我以前做过,效果很好。我要说的主要障碍是应用更先进/复杂的轴心选择算法的实际效率低下。如果没有随机访问,即使是简单的中位数3,也需要完全通过列表。然而,最近的趋势可能会使这一点过时。我知道每一次随机访问都需要在链表中花费O(n)个时间。但在我看来,每次比较都需要O(1)时间,而不是O(n)。你能指出QuasRoad中的哪个步骤比链表需要更多的时间吗?@泽弗-考虑最坏的例子,其中每个递归级别的最大分区只减少了1,这意味着递归的N-1级,和(n-1递归级)对于每个O级(n ^ 2)的时间复杂度递归的比较。最坏情况复杂度为O(n^2)。但即使在链表中,它也应该是O(n^2)。我不明白链接列表中的O(n^3)是怎么回事。@Zephyr-我更新了我的答案并删除了对O(n^3)的引用。我在考虑另一种情况。@Zephyr-您可以使用快速排序的一种变体来消除交换,但它的最坏情况时间复杂度仍然是O(n^2)。对于每个递归级别,第一个节点用作枢轴,并创建3个列表,节点<枢轴,节点==枢轴,节点>枢轴。递归用于第一个子列表和第三个子列表,然后将这三个列表链接在一起。