Joh*_*lla 49
其中一个主要因素是快速排序具有更好的参考局部性 - 接下来要访问的内容通常与您刚才看到的内容非常接近.相比之下,堆垛突然跳得更多.由于紧密相连的东西可能会被缓存在一起,因此快速排序往往会更快.
然而,quicksort的最坏情况表现明显比heapsort更差.因为一些关键应用程序需要保证速度性能,所以heapsort是这种情况的正确方法.
Mar*_*eli 16
Heapsort是O(N log N)保证,比Quicksort的最坏情况要好得多.根据Mergesort的需要,Heapsort不需要为另一个数组提供更多内存来放置有序数据.那么为什么商业应用程序坚持使用Quicksort?Quicksort有什么特别优于其他实现?
我自己测试了算法,我发现Quicksort确实有一些特别的东西.它运行速度快,比Heap和Merge算法快得多.
Quicksort的秘诀在于:它几乎不会进行不必要的元素交换.交换是耗时的.
使用Heapsort,即使您的所有数据都已经订购,您也要交换100%的元素来订购数组.
使用Mergesort,情况会更糟.您将在另一个数组中编写100%的元素,并将其写回原始数组中,即使已经订购了数据.
使用Quicksort,您不会交换已订购的内容.如果您的数据是完全订购的,那么几乎没有任何交换!虽然关于最坏情况有很多烦恼,但是对于枢轴选择的一点改进,除了获得数组的第一个或最后一个元素之外,可以避免它.如果从第一个,最后一个和中间元素之间的中间元素获得一个枢轴,则避免最坏的情况是足够的.
Quicksort的优势不是最坏的情况,而是最好的情况!在最好的情况下,你做相同数量的比较,好吧,但你几乎没有交换.在一般情况下,您交换部分元素,但不是所有元素,如Heapsort和Mergesort.这就是Quicksort最好的时间.交换更少,速度更快.
我的计算机上的C#下面的实现,在发布模式下运行,使用中间数据枢轴击败Array.Sort 3秒,使用改进的数据透视表击败2秒(是的,有一个开销可以获得良好的支点).
static void Main(string[] args)
{
int[] arrToSort = new int[100000000];
var r = new Random();
for (int i = 0; i < arrToSort.Length; i++) arrToSort[i] = r.Next(1, arrToSort.Length);
Console.WriteLine("Press q to quick sort, s to Array.Sort");
while (true)
{
var k = Console.ReadKey(true);
if (k.KeyChar == 'q')
{
// quick sort
Console.WriteLine("Beg quick sort at " + DateTime.Now.ToString("HH:mm:ss.ffffff"));
QuickSort(arrToSort, 0, arrToSort.Length - 1);
Console.WriteLine("End quick sort at " + DateTime.Now.ToString("HH:mm:ss.ffffff"));
for (int i = 0; i < arrToSort.Length; i++) arrToSort[i] = r.Next(1, arrToSort.Length);
}
else if (k.KeyChar == 's')
{
Console.WriteLine("Beg Array.Sort at " + DateTime.Now.ToString("HH:mm:ss.ffffff"));
Array.Sort(arrToSort);
Console.WriteLine("End Array.Sort at " + DateTime.Now.ToString("HH:mm:ss.ffffff"));
for (int i = 0; i < arrToSort.Length; i++) arrToSort[i] = r.Next(1, arrToSort.Length);
}
}
}
static public void QuickSort(int[] arr, int left, int right)
{
int begin = left
, end = right
, pivot
// get middle element pivot
//= arr[(left + right) / 2]
;
//improved pivot
int middle = (left + right) / 2;
int
LM = arr[left].CompareTo(arr[middle])
, MR = arr[middle].CompareTo(arr[right])
, LR = arr[left].CompareTo(arr[right])
;
if (-1 * LM == LR)
pivot = arr[left];
else
if (MR == -1 * LR)
pivot = arr[right];
else
pivot = arr[middle];
do
{
while (arr[left] < pivot) left++;
while (arr[right] > pivot) right--;
if(left <= right)
{
int temp = arr[right];
arr[right] = arr[left];
arr[left] = temp;
left++;
right--;
}
} while (left <= right);
if (left < end) QuickSort(arr, left, end);
if (begin < right) QuickSort(arr, begin, right);
}
Run Code Online (Sandbox Code Playgroud)
这里有几个解释:
http://www.cs.auckland.ac.nz/software/AlgAnim/qsort3.html
http://users.aims.ac.za/~mackay/sorting/sorting.html
基本上,尽管快速排序的最坏情况是O(n ^ 2),但它平均表现更好.:-)