快速排序算法 - 做同一件事的许多不同方法?
Quick Sort Algorithms - Many different ways of doing the same thing?
我说有很多方法可以执行快速排序对吗?
为了便于论证,让我们使用第一本教科书的编号:
20 47 12 53 32 84 85 96 45 18
这本书说要交换 18 和 20(书中 20 是红色的,18 是蓝色的,所以我把 20 加粗了)。
基本上它一直移动蓝色指针直到数字是:
18 12 20 53 32 84 85 96 45 47
现在它说(这对我来说很明显)20 左边的所有数字都小于,右边的所有数字都大于,但它从未将 20 命名为 "pivot",这是大多数其他资源谈论它的方式。然后正如所有其他方法所述,它在两侧进行快速排序,然后我们得到(它只涵盖对列表的右半部分进行排序):
47 32 45 53 96 85 84 本书结束。现在我从其他资源中了解到,一旦所有列表都按顺序排列,它们就会重新组合在一起。我想我理解这一点,但经常被一本 "Cambridge approved" 与第二本不同的教科书搞糊涂。第二个讲的是通过选择中位数来找到一个支点。
查找列表 "pivot" 的最佳方法是什么?
理论上-选择median元素作为枢轴可以保证最少的递归调用次数,并保证Theta(nlogn)
运行时间。
但是,找到这个中位数是通过 selection algorithm - and if you want to guarantee selection takes linear time - it needs median of medians 算法完成的,该算法的常量很差。
如果您选择第一个(或最后一个)元素作为基准 - 您肯定会在排序或几乎排序的数组中获得较差的性能 - 这很可能是许多应用程序中的输入数组 - 所以这不是一个好主意选择要么。所以选择数组的 first/last 元素实际上是一个坏主意。
选择枢轴的一个很好的解决方案 - 是随机。从 r = rand([0,length(array))
中抽取一个随机数,然后选择第 r 个元素作为你的基准。
虽然理论上存在最坏情况的可能性 - 它是:
- 不太可能
- 恶意用户很难预测最坏情况下的输入是什么,尤其是当他不知道随机函数 and/or 种子时。
你的教科书上讲的和pivot-based的概念差不多,只是那边没有提到这个术语。但是,无论如何,概念是相同的。
What's the best way to find a "pivot" for a list?
没有固定的 select 关键元素的方法。您可以 select 数组的任何元素——第一个、第二个、最后一个等。对于给定的数组,它也可以随机 selected。
但是,科学家和数学家通常会说中值元素,因为基于对称性的原因,它是列表的中间元素,从而减少递归调用。
很明显,当您 select 数组的第一个或最后一个元素时,递归调用的次数会更多 --- 从而更接近最坏的情况。递归调用的次数越多,将被框起来分别对两个分区进行快速排序。
我说有很多方法可以执行快速排序对吗?
为了便于论证,让我们使用第一本教科书的编号: 20 47 12 53 32 84 85 96 45 18
这本书说要交换 18 和 20(书中 20 是红色的,18 是蓝色的,所以我把 20 加粗了)。
基本上它一直移动蓝色指针直到数字是: 18 12 20 53 32 84 85 96 45 47
现在它说(这对我来说很明显)20 左边的所有数字都小于,右边的所有数字都大于,但它从未将 20 命名为 "pivot",这是大多数其他资源谈论它的方式。然后正如所有其他方法所述,它在两侧进行快速排序,然后我们得到(它只涵盖对列表的右半部分进行排序):
47 32 45 53 96 85 84 本书结束。现在我从其他资源中了解到,一旦所有列表都按顺序排列,它们就会重新组合在一起。我想我理解这一点,但经常被一本 "Cambridge approved" 与第二本不同的教科书搞糊涂。第二个讲的是通过选择中位数来找到一个支点。
查找列表 "pivot" 的最佳方法是什么?
理论上-选择median元素作为枢轴可以保证最少的递归调用次数,并保证Theta(nlogn)
运行时间。
但是,找到这个中位数是通过 selection algorithm - and if you want to guarantee selection takes linear time - it needs median of medians 算法完成的,该算法的常量很差。
如果您选择第一个(或最后一个)元素作为基准 - 您肯定会在排序或几乎排序的数组中获得较差的性能 - 这很可能是许多应用程序中的输入数组 - 所以这不是一个好主意选择要么。所以选择数组的 first/last 元素实际上是一个坏主意。
选择枢轴的一个很好的解决方案 - 是随机。从 r = rand([0,length(array))
中抽取一个随机数,然后选择第 r 个元素作为你的基准。
虽然理论上存在最坏情况的可能性 - 它是:
- 不太可能
- 恶意用户很难预测最坏情况下的输入是什么,尤其是当他不知道随机函数 and/or 种子时。
你的教科书上讲的和pivot-based的概念差不多,只是那边没有提到这个术语。但是,无论如何,概念是相同的。
What's the best way to find a "pivot" for a list?
没有固定的 select 关键元素的方法。您可以 select 数组的任何元素——第一个、第二个、最后一个等。对于给定的数组,它也可以随机 selected。
但是,科学家和数学家通常会说中值元素,因为基于对称性的原因,它是列表的中间元素,从而减少递归调用。
很明显,当您 select 数组的第一个或最后一个元素时,递归调用的次数会更多 --- 从而更接近最坏的情况。递归调用的次数越多,将被框起来分别对两个分区进行快速排序。