我知道快速排序的时间复杂性。但我想知道如何创建最坏情况的排列。
我想有一条规则要做到。我认为它真的很多,但对我来说太难了。
请告诉我如何创建三个快速排序中位数的最坏情况,而不是正常快速排序。 (例如,如果pivot是列表中最左侧的项目,列表的最坏情况排列是排序列表,但是pivot的中位数是3?)
答案 0 :(得分:4)
不幸的是,没有通用的答案,因为它取决于如何实现“三个中间”部分的实现,以及如何实现“分区”步骤。许多人很容易通过给他们提供大量相同的元素来处理最坏的情况。但对于更有趣的案例,一般概念就是这样。
你从数字1 ...... N开始,和一个相同大小的未知数组。你还不知道哪个数字在哪个索引中。
1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20
[ A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T]
快速排序的最坏情况是当拾取的枢轴尽可能接近一端时,因此您需要三个中最大(或最小)的三个元素,这些元素将被考虑用于中位数。通常,(但不总是!)第一个,中间和最后一个元素。
1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17
[19, B, C, D, E, F, G, H, I,18, K, L, M, N, O, P, Q, R, S,20]
现在我们知道在分区步骤之后,数组可能看起来像这样,具体取决于分区的实现方式:
[ S, B, C, D, E, F, G, H, I,18, K, L, M, N, O, P, Q, R,19,20]
^ pivot
然后它会在[18-R]小节上递归。 (它可能会或可能不会在[20]小节上进一步递归,但我们无法在那里做更多的事情。所以我们重复这个模式,将剩下的两个最大元素放在剩下的最后和中间:
[16, B, C, D, E, F, G, H,15,18, K, L, M, N, O, P, Q,17]
所以在分区后它看起来像:
[ P, B, C, D, E, F, G, H,15, Q, K, L, M, N, O,16,18,17]
^ pivot
然后我们继续处理下一小节:
[ P, B, C, D, E, F, G, H,15, Q, K, L, M, N, O]
请注意,当我们填写“最大”元素时,我们将用数字替换数组位置(字母)。当我们完成后,我们将知道每个阵列位置中的数字。到目前为止,我有这个:
[19, B, C, D, E, F, G, H,15,18, K, L, M, N, O, P, Q,17,19,20]
不幸的是,正如我所提到的,它在很大程度上取决于如何选择数据透视以及如何实现分区。可能存在一个你可以填写的简单模式,但我不知道它会是什么。您还会注意到我一直将最前三位的中位数放在最左侧,因为这使得大多数分区实现更加相似,但实际上,如果您知道分区如何工作,那么放置中位数可能会更好在其他两个可能的位置之一中排名前三位,只是为了再做一次交换。
答案 1 :(得分:3)
不可能创建一个项目排列,这将导致所有或甚至大多数Quicksort实现表现出最坏情况的行为。事实上,根据排序的实现方式,一次运行中的最坏情况数组在后续运行中可能会很好。如果实现使用中间随机三来选择枢轴,并且每次调用例程时使用不同的种子,就会发生这种情况。
C qsort
函数以及许多其他库中的排序库函数很容易受到Quicksort杀手"但是,算法使用比较回调中提供的信息来动态创建最坏情况。令人惊讶的是,这并不困难。例如,请参阅A Killer Adversary for Quicksort。