Quicksort奇怪的结果?

时间:2013-08-25 20:20:01

标签: c++ arrays sorting partitioning quicksort

我最近学到了quicksort。我读到枢轴选择在整体性能中起着非常重要的作用。 我有一个任务,我应该在不同的输入大小上测试三个枢轴选择的变化 - 随机化,三个中位数和中位数中位数。 我曾经读过,即使在最坏的情况下,中位数版本的中位数也不会在O(n2)中运行。但在我的研究结果中,随机化和三个版本的中位数给出了几乎相似的结果,三个中位数稍好一些,但中位数的中位数表现非常差几个数量级。例如,在输入大小为50000时,随机版本在16547 us中运行,而中位数的中位数在1139168 us中运行。 有人可以解释为什么会这样吗? (据我所知,我已经正确实施了枢轴选择算法 - 将数组潜入5组,取每组的中位数,然后再次递归执行此操作,直到得到中位数。)我做错了什么?

编辑:我正在重新检查代码以防万一,但是中位数实现的中位数与其他两个实现一样慢或甚至更慢(如果只是略微)工作是正常的还是保证工作得更快?

Edit2:这是我用来查找中位数中位数的代码,它找到的值返回到快速排序函数以用作枢轴。我确信代码违反了所有良好的编码习惯,请将此归于我的noob-ishness,并尝试超越它。

int getpivot(int arr[], int low, int high) {

        int i,j,k,l,val,med[MAX/4],temp[6],pivot,mi,index,temp2;
        if(high-low+1<=5) { //returns median if size of array<=5
            for(i=1;i<=high;i++) {
                val=arr[i];
                j=i-1;
                while(j>=0 && val<arr[j]) {
                    arr[j+1]=arr[j];
                    j--;
                }
                arr[j+1]=val;
            }
            return arr[(low+high)/2];   
        }

        mi=0;
        // divide array into groups of 5, 
        //finds median of those groups by insertion sorting
        //adds these medians to med array
        for(i=low;i+5<=high;) {
            index=0;
            for(j=i;j<i+5;j++)
                temp[index++]=arr[j];
            i+=5;
            for(k=1;k<5;k++) {
                val=temp[k];
                l=k-1;
                while(l>=0 && temp[l]>val) {
                    temp[l+1]=temp[l];
                    l--;
                }
                temp[l+1]=val;
            }
            med[mi++]=temp[2];
        }


        //choose random index as pivot and partition the med array
        pivot=rand()%mi;
        i=low=0;
        j=high=mi-1;

        while(i<j) {
            while(i<high && med[i]<=med[pivot]) i++;
            while(med[j]>med[pivot]) j--;
            if(i<j) {
                temp2=med[i];
                med[i]=med[j];
                med[j]=temp2;
            } 
        }
        temp2=med[j];
        med[j]=med[pivot];
        med[pivot]=temp2;

        //j is final position of pivot
        //see if j is left/right or equal to the position of true median of median
        // and recurse accordingly

        low/=5;
        high/=5;
        if(j==(low+high)/2) return med[j];
        else if(j<(low+high)/2) return getpivot(med,j+1,high);
        else return getpivot(med,low,j-1);

    }

1 个答案:

答案 0 :(得分:1)

您的观察结果有点正确。

随机三个支点选择的中位数应该会带来良好的Quicksort效果,而后者显着更好,如R. Sedgewick的recommended。< / p>

如果阵列在每一步被分成相等的一半(即中位数是枢轴),则在最坏的情况下可以使{QAME}成为O(nlogn)。现在,中位数中位数算法可以找到线性时间的中位数,使得Quicksort O(nlogn)处于最坏的情况。

然而,中位数中位数的开销非常高,几乎从未在实践中使用过,因为它会导致性能下降得多。因此,不能仅根据时间复杂度来判断算法的速度,还需要考虑常数因素。