【问题标题】: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) 表示,对其进行快速排序并恢复为原始表示。

标签: c++ algorithm quicksort


【解决方案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。具体有什么不明白的请追问,我会尽量详细说明。
  • 我在分区函数中创建了子数组。你是认真的吗?之后我做什么?
猜你喜欢
  • 2012-04-25
  • 2020-08-14
  • 2014-10-10
  • 2020-07-30
  • 2016-12-23
  • 1970-01-01
  • 2014-12-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多