当前位置: 首页 > 知识库问答 >
问题:

如果有更多重复密钥,快速排序算法的改进

涂选
2023-03-14

我正在阅读Robert Sedwick算法和数据结构第1-4部分的书中的快速排序算法。

template <class item>

static void quicksort(item [] a, int l, int r)
{
    if(r <= l) return;
    int i = partition(a,l,r);
    quicksort(a, l, i-1);
    quicksort(a, i+1, r);
}

template <class item>
int partition(item a[], int l, int r)
{
    int i = l-1; j = r; item v = a[r];

    for(;;) {
        while( a[++i] < v );
        while( v < a[--j] ) 
            if( j == l ) 
                break;
        if( i >= j) 
            break;  // pointer crossing.
        exch(a[i], a[j]);
    }

    exch(a[i], a[r]);
    return i;
}

书中有以下关于上述算法的文字。

当文件中存在重复键时,指针交叉很微妙。我们可以稍微改进分区过程,当我

我的问题是

  1. 我们如何用下面的描述修改上面的程序?我在修改它以理解文本方面有困难。
  2. 为什么上面的快速排序算法不能有效地工作,如果存在更多的重复密钥。
  3. 如果存在更多的复制键,上述修改如何改进?
  4. 作者所说的第一个分区在调用快速排序(a, i 1, r)中退化是什么意思,因为它的最右键是它的最小键。作者这里所说的堕落是什么意思?

谢谢你的时间和帮助。

共有1个答案

孔俊捷
2023-03-14

当你为i==j而中断时 从第一个while循环开始,您必须有a[i]

在这种情况下,最外层的exch(a[i],a[r]) 只需将枢轴值交换给自身
因此,在下一个递归调用快速排序(a,i 1,r)对于数组的右半部分,最小元素位于最右边。(您的透视选择策略很简单,项v=a[r];)我们都知道,快速排序选择数组中最小或最大的透视元素是不好的。因此,对右半部分的后续递归调用将是退化调用<这就是为什么作者建议不要因为i==j而中断,而是在这之前抓住它们

这里的退化意味着,递归树变得倾斜,即随后的问题没有产生几乎相等的大小。你把一个大小的问题分成大小的问题,比如N-1和1的问题,而不是更平衡的问题,比如把它分成大小的问题2.

我们可以按如下方式实施:

int partition(int A[], int l, int r){
        int i=l-1, j=r, v = A[r];
        for(;;){
                while(A[++i] < v);
                while(A[--j] > v)
                        if(j == l)
                                break;
                if(i>=j)
                        break;
                swap(A[i], A[j]);
        }
        if(i == j){// case when we stopped at the pivot element.
                j = j+1;//backtrack j 1 step.
                if(j <= r)
                    swap(A[j], A[r]);
                return j;// partition the subsequent problems around j now.
        }
        swap(A[i], A[r]);
        return i;
}

 类似资料:
  • 主要内容:快速排序算法的实现提到排序算法,多数人最先想到的就是快速排序算法。快速排序算法是在分治算法基础上设计出来的一种排序算法,和其它排序算法相比,快速排序算法具有效率高、耗费资源少、容易实现等优点。 快速排序算法的实现思路是: 从待排序序列中任选一个元素(假设为 pivot)作为中间元素,将所有比 pivot 小的元素移动到它的左边,所有比 pivot 大的元素移动到它的右边; pivot 左右两边的子序列看作是两个待排

  • 快速排序,这是一个经典的算法,本文给出几种python的写法,供参考。 特别是python能用一句话实现快速排序。 思路说明 快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。 (1) 分治法的基本思想 分治法的基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解

  • JavaScript算法-快速排序 快速排序是处理大数据集最快的排序算法之一。它是一种分而治之的算法,通过递归的方式将数据依次分解为包含较小元素和较大元素的不同子序列。该算法不断重复这个步骤直到所有数据都是有序的。 这个算法首先要在列表中选择一个元素作为基准值(pivot)。数据排序围绕基准值进行,将列表中小于基准值的元素移到数组的底部,将大于基准值的元素移到数组的顶部。 快速排序的算法和伪代码

  • 我知道它是如何工作的,如果我不知道的话,网上有很多资料供我查阅。我在这里遇到的问题是,我找到的一些文章陈述如下(来自维基百科): 对数组重新排序,使所有值小于透视的元素都在透视之前,而所有值大于透视的元素都在透视之后(相等的值可以从任一方向移动)。分区后,枢轴处于其最终位置。这称为分区操作。 其他一些消息来源,(hackerrank视频): 第二种方法与枢轴本身无关,但它将确保所有比枢轴小的元素在

  • 本文向大家介绍Python实现快速排序算法及去重的快速排序的简单示例,包括了Python实现快速排序算法及去重的快速排序的简单示例的使用技巧和注意事项,需要的朋友参考一下 快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用。 该方法的基本思想是: 1.先从数列中取出一个数作为基准数。 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。

  • 本文向大家介绍C#排序算法之快速排序解析,包括了C#排序算法之快速排序解析的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了C#实现快速排序的具体代码,供大家参考,具体内容如下 代码: 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。