如何使用数组的中位数作为快速排序的枢轴

时间:2011-10-28 20:15:50

标签: java algorithm sorting quicksort

我必须编写一个快速排序算法,该算法使用数组的中位数作为枢轴。根据我在书中读到的一般理解,我必须使用选择算法,其中我将数组拆分为n / 5个子数组,使用插入排序对每个子数组进行排序,找到中位数,然后递归调用选择算法来查找中位数的中位数。我甚至不确定如何开始这个,我很困惑。 selectMedian算法调用应该看起来像这样:SelectMedian(int first,int last,int i)其中i是我想要选择的第i个索引(在这种情况下它将是中间索引,所以array.length / 2 )。本书即时阅读给出了它的描述:

The algorithm in words (if n>1):

1. Divide n elements into groups of 5
2. Find median of each group (use insertion sort for this)
3. Use Select() recursively to find median x of the  n/5
medians
4. Partition the n elements around x.  Let k = rank(x)
5. if (i == k) then return x
if (i < k) then use Select() recursively to find i-th
smallest element in first partition else (i > k) use 
Select() recursively to find (i-k)th smallest element in 
last partition.

有人可以协助我编写这个算法吗?谢谢!

3 个答案:

答案 0 :(得分:3)

真的有必要吗?为什么不使用三个的中位数,根据三个值的中位数选择枢轴,即。第一个,中间和最后一个值。

或者您甚至可以使用随机枢轴,这将大大降低机会最终使用QuickSort的最坏情况时间O(N²),也可能是适合您的实施。

答案 1 :(得分:0)

我假设你可以找出每个包含5个元素的n / 5个子阵列。

查找子阵列的中位数非常简单:查看每个元素并找到包含两个较小元素的元素。

例如,您有1 4 2 3 5. 1没有更小的元素。 4有三个较小的元素。 2有一个较小的元素。 3有两个较小的元素;这是你想要的那个。

现在你找到了n / 5个中位数。你想找到中位数的中位数,所以你再次运行算法。

示例:

1 7 2 4 9 0 3 8 5 6 1 4 7 2 3

[1 7 2 4 9] [0 3 8 5 6] [1 4 7 2 3]

findMedian([1 7 2 4 9])= 4;

findMedian([0 3 8 5 6])= 5;

findMedian([1 4 7 2 3])= 3;

[4 5 3]

findMedian([4 5 3])= 4;

4是你的支点。

这样做的原因是尝试均匀分割阵列;如果你的数组被分割不平衡,你将获得O(N ^ 2)的性能;如果您的阵列均匀分割,则会获得O(NlogN)性能。

选择一个随机数据块意味着你可以得到任何一个 - 实际上它会平衡到O(NlogN),但很多应用程序需要一致的性能,并且随机快速排序从运行到运行

我们使用5(而不是3或7)的原因是因为我们正在添加另一个时间复杂度项来搜索中位数 - 这个项必须小于O(NlogN)但是你希望它小到尽可能。使用3可以获得O(N ^ 2),使用5可以得到O(NlogN),而5是最小的数字,这是真的。

(Blum,Floyd,Pratt,Rivest和Tarjan在其1973年的论文“时间界限选择”中给出了线性时间中位数的算法,并回答了一个着名的开放问题)

答案 2 :(得分:0)

QUICKSORT2(A, p, r)
if p<r
    median=floor((p + r) /2) - p + 1
    q=SELECT(A, p, r, median)
    q=PARTITION2(A, p, r, q)
    QUICKSORT2(A, p, q-1)
    QUICKSORT2(A, q+1, r)

PARTITION2(A, p, r, q)
switch between A[r] and A[q]
return PARTITION(A, p, r)