繁体   English   中英

快速排序重复项

[英]Quicksort for duplicates

我编写了以下代码以进行快速排序,对于唯一数字来说似乎做得很好。
但是,当存在重复项时,它会失败。
感谢您对重复项进行调整:

class QuickSort{

    public static void sort(int left,int right,int[] data){
            if(right-left <= 0) return;
            int pivot=organize(left,right,data);
            sort(left,pivot-1,data);
            sort(pivot,right,data);
        }

        private static int organize(int left,int right,int[] data){
            int _right=right;
            int _left=left;
            int pivot=(left+right)%2==0?(left+right)/2:(left+right+1)/2;
            //Move the pivot to the extreme right.
            int pivotval=data[pivot];
            swap(pivot,right,data);
            left=left-1;//to adjust teh stating pointer
            while(true){

                while(right > 0 &&  data[--right]>pivotval);
                while(data[++left]<pivotval);
                if(right<=left) break;
                swap(left,right,data);

            }
            swap(left,_right,data);
            return left;
        }

        private static void swap(int left,int right,int[] data){
            int temp=data[right];
            data[right]=data[left];
            data[left]=temp;
        }

public static void main(String[] args){
                int N=Integer.parseInt(args[0]);
            int[] data=new int[N];
            Random r=new Random();
                    for(int i=0 ;i<N;i++)
                data[i]=r.nextInt(N);

                //After populating the array
                QuickSort.sort(0,data.length-1,data);

            }



            }

您应该决定如何使用相等的元素。 最简单的解决方案是将它们放在右侧说的一侧:

        while(true){

            while(right > 0 &&  data[--right]>=pivotval);
            while(data[++left]<pivotval);
            if(right<=left) break;
            swap(left,right,data);

        }

这里的问题是该算法在某些情况下会非常慢。 更好的方法是形成相等元素的第三个区域,该区域从枢轴开始在数组的中心增长。

一种更简单易用的方法进行了两次迭代-第一个迭代是过滤比枢轴大的元素以在数组的右端形成一组,第二个则在左端形成一组较小的元素。 两者之间的任何事物都等于枢轴。

希望这可以帮助。

while(right> 0 && data [-right]> pivotval);

您需要撤销此测试,否则您将无处可寻。

您将枢轴移到最右端,但是当您希望在while循环后换回枢轴时,可以调用swap(left,_right,data); ,但left不等于ivotpivot=(left+right)%2==0?(left+right)/2:(left+right+1)/2; ,但不确定。 看来您想使用Hoare-Partition。 这里是:

private static int organize(int left,int right,int[] data){
        int pivot=(left+right)%2==0?(left+right)/2:(left+right+1)/2;
        //Move the pivot to the extreme right.
        int pivotval=data[pivot];
        //swap(pivot,right,data);
        left=left-1;//to adjust the stating pointer
        right = right + 1;
        while(true){

            while(right > 0 &&  data[--right]>pivotval);
            while(data[++left]<pivotval);
            if(right<=left) break;
            swap(left,right,data);

        }
        //swap(left,right,data);
        return left;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM