快速排序的改进

Posted

技术标签:

【中文标题】快速排序的改进【英文标题】:Improvement of quick sort 【发布时间】:2015-03-19 08:07:55 【问题描述】:

快速排序算法在有很多副本时表现不佳。(我的意思是我们有重复数据)。如何改进这个问题。

int partition (int low,int high)

 int j=low,i=low+1;
 int PivotItem=arr[low];
  for(int i=0,j=0;i<n;i++)
 
    if(arr[i]==PivotItem)
     subarray[j]=arr[i];
 
 for(i=low+1;i<=high;i++)

    if(arr[i]<PivotItem)
    
        j++;
        swap(arr[i],arr[j]);
    

swap(arr[low],arr[j]);
int PivotPoint=j;
return PivotPoint;

void quick_sort(int low,int high)

if(low==high)
    return ;
int PivotPoint=partition(low,high);
quick_sort(low,PivotPoint-1);
quick_sort(PivotPoint+1,high);

【问题讨论】:

您的目标是特定的语言平台吗?在 Java 中,Collections.sort() 实际上会进行合并排序,尤其是为了避免不必要的数据复制。在 C++ 中,您有单独的 sort(合并)和 qsort(快速排序)。另外,您所说的“项目副本”是什么意思?如果您有涉及重复的数字列表,则不能说它们是副本。他们只是复制部分数据。 你的意思是很多重复的项目还是重复很多次的项目? @YvesDaoust:例如,我们有 111133333332222999999999000000031115553333。 尝试每层缩进 4 个空格。 可以选择压缩数据:将序列转换为(value, repeat count) 表示,对其进行快速排序并恢复为原始表示。 【参考方案1】:

QuickSort 有一个特殊的修改,称为dutch flag sort algorithm。它对小于、等于和大于枢轴项值的项使用三向分区。

【讨论】:

在此之上,可以使用双支点实现三向分区。 @greybeard 你的意思是iaroslavski.narod.ru/quicksort/DualPivotQuicksort.pdf 吗?当然,该算法对于许多重复项的情况都有好处(但似乎并不能完全解决问题) 这将是引用次数最多的论文的最值得注意的 URL。这是对具有统一访问时间的通用排序的公平尝试。 几个不重复的键似乎比许多键重复更容易。【参考方案2】:

我假设您的意思是快速排序基于&lt;=(或&lt;,然后结果与下一个解释对称)比较器比较元素,如果我们看一下所有元素都是与枢轴x 相同,您将获得快速排序的最坏情况复杂性,因为您将数组分成两个非常不均匀的部分,一个大小为n-1,另一个为空。


解决此问题的快速解决方法是仅对 &lt;&gt; 使用快速排序 - 将数据拆分为两个子数组,而不是单个枢轴,保存一个数组保存所有等于pivot的元素,然后对严格大于pivot的元素和严格小于pivot的元素进行递归,合并三个数组。

插图:

legend: X=pivot, S = smaller than pivot, L = larger than pivot
array = |SLLLSLXLSLXSSLLXLLLSSXSSLLLSSXSSLLLXSSL|
Choose pivot - X
Create L array of only strictly smaller elements:  |SSSSSSSSSSSSSSS|
Create R array of only strictly larger elements: |LLLLLLLLLLLLLLLLLL|
Create "pivot array" |XXXXXX|

Now, recurse on L, recurse on R, and combine:
|SSSSSSSSSSSSSSS XXXXXX LLLLLLLLLLLLLLLLLL|

【讨论】:

我把我的代码放在我的问题中。如何在我的代码中实现你的解决方案? @sarina 你需要让partition 持有一个所有元素的子数组等于主元(或元素范围),当你完成后,递归从l 开始这个子数组的末尾,从这个子数组的末尾到r。具体有什么不明白的请追问,我会尽量详细说明。 我在分区函数中创建了子数组。你是认真的吗?之后我做什么?

以上是关于快速排序的改进的主要内容,如果未能解决你的问题,请参考以下文章

Java快速排序

Java快速排序

快速排序的改进

如果更多重复键,则快速排序算法改进

面试官:手写一个快速排序,并对其改进

快速排序的思考与改进