Java FlagSort-分而治之-小麻烦

Java FlagSort-分而治之-小麻烦,java,sorting,recursion,stack-overflow,divide-and-conquer,Java,Sorting,Recursion,Stack Overflow,Divide And Conquer,在执行一个特定的排序算法时,我遇到了一个连谷歌都不想帮我解决的问题。。。首先关于算法的一些话: 最重要的部分是将输入(数组)划分为三个部分:选择两个关键数字(红色和蓝色,断言红色=3,由一个键值组成:如果再次分区,无论选择了什么轴,所有元素随后都放在同一个分区中,最终会遇到堆栈溢出。这就是为什么我认为您可以帮我解决问题,,因为我确信有解决方案 强制性JavaCode代码片段:分区-很抱歉德语调试,太懒了,无法翻译它。IntTuple只能保存两个整数;没有什么太荒谬的 public static

在执行一个特定的排序算法时,我遇到了一个连谷歌都不想帮我解决的问题。。。首先关于算法的一些话

最重要的部分是将输入(数组)划分为三个部分:选择两个关键数字(红色和蓝色,断言红色=3,由一个键值组成:如果再次分区,无论选择了什么轴,所有元素随后都放在同一个分区中,最终会遇到堆栈溢出。这就是为什么我认为您可以帮我解决问题,,因为我确信有解决方案

强制性JavaCode代码片段:分区-很抱歉德语调试,太懒了,无法翻译它。IntTuple只能保存两个整数;没有什么太荒谬的

public static IntTuple partition(int[] E, int left, int right, int red, int blue){
    if (red > blue) {
        int v = red;
        red = blue;
        blue = v;
    }
    System.out.println("Partition Eingabe: " + Arrays.toString(E) + " Links=" + left + " Rechts=" + right + " Rot=" + red + " Blau=" + blue);
    /*
     * Es gilt r <= b, also gilt für beliebige x...
     * ... x < r => x < b
     * ... x > b => x > r.
     *
     * Das Gerüst für diesen Algorithmus wurde kopiert von Folie 7-13
     */
    IntTuple result = new IntTuple (left, right); // rote und blaue Regionen sind leer
    int u = left; // weiße Region ist leer, die unbekannte == E[left...right]
    while (u <= result.v2) {
        System.out.print("E[" + u + "]: ");
        if (E[u] < red) {
            System.out.print("rot  ");
            swap(E, result.v1, u);
            result.v1++; // vergrößere die rote Region
            u++; // verkleinere die unbekannte Region
        } else if ((E[u] >= red) && (E[u] <= blue)) {
            System.out.print("weiß ");
            u++; // verkleinere die unbekannte Region
        } else if (E[u] > blue) {
            System.out.print("blau ");
            swap(E, result.v2, u);
            result.v2--; // vergrößere die blaue Region
        }
        System.out.print("Partition Schritt: [");
        for(int i = left; i < right; i++)
            System.out.print("" + E[i] + " ");
        System.out.println("" + E[right] + "]");
    }
    System.out.print("Partition Ausgabe: [");
    for(int i = left; i < right; i++)
        System.out.print("" + E[i] + " ");
    System.out.println("" + E[right] + "]" + " RotG=" + result.v1 + " BlauG=" + result.v2);
    return result;
}
publicstaticinttuple分区(int[]E,int-left,int-right,int-red,int-blue){
如果(红色>蓝色){
int v=红色;
红色=蓝色;
蓝色=v;
}
System.out.println(“分区Eingabe:”+Arrays.toString(E)+“Links=“+left+”Rechts=“+right+”Rot=“+red+”Blau=“+blue”);
/*
*Es镀金Rxb=>x>r。
*
*第7-13页
*/
IntTuple result=新的IntTuple(左、右);//死记硬背
int u=left;//weiße区域是leer,die unbekannte==e[左…右]
而(u=红色)和(E[u]蓝色){
系统输出打印(“blau”);
互换(E、result.v2、u);
result.v2-->//vergrößere die blaue地区
}
System.out.print(“分区Schritt:[”);
for(int i=左;i<右;i++)
系统输出打印(“+E[i]+”);
System.out.println(“+E[右]+”]);
}
系统输出打印(“分区Ausgabe:[”);
for(int i=左;i<右;i++)
系统输出打印(“+E[i]+”);
System.out.println(“+E[右]+”]“+”RotG=“+result.v1+”BlauG=“+result.v2”);
返回结果;
}
必需的Java代码片段:排序

private static void flagSort(int[] E, int left, int right){
    System.out.println("Sortiere: " + left + " bis " + right);
    if(left < right - 1) {
        Random rnd = new Random();
        IntTuple v = partition(E, left, right, rnd.nextInt(50), rnd.nextInt(50));
        //IntTuple v = partition(E, left, right, E[left], E[left + 1]);
        flagSort(E, left, v.v1 - 1);
        flagSort(E, v.v1, v.v2);
        flagSort(E, v.v2 + 1, right);
    } else if((left == right - 1) && (E[left] > E[right])) {
        swap(E, left, right);
    }
}
private static void flagSort(int[]E,int left,int right){
System.out.println(“Sortiere:+左+”双“+右);
如果(左<右-1){
随机rnd=新随机();
IntTuple v=分区(E,左,右,rnd.nextInt(50),rnd.nextInt(50));
//整数组v=分区(E,左,右,E[left],E[left+1]);
旗标排序(E,左,v.v1-1);
flagSort(E,v.v1,v.v2);
flagSort(E,v.v2+1,右);
}else如果((左==右-1)和&(E[左]>E[右]){
交换(E,左,右);
}
}
非常感谢您的建议

你好,阿尔德尔

更多:我想出了一个笨拙的解决方案:

private static void flagSort(int[] E, int left, int right, boolean dual){
    if(left < right) { // Singleton or empty segments are already sorted!
        IntTuple v;
        if(dual) // The last step has produced only a single white partition.
            // Treat this partition with double pivot
            v = partition(E, left, right, E[left], E[left]);
        else    // The last step has produced more than one partition, go on normally.
            v = partition(E, left, right, E[left], E[left + 1]);
        // Analyze partitions
        if((left != v.v1) || (right != v.v2)) {
            // 2 or 3 partitions available. Descend further.
            flagSort(E, left, v.v1 - 1, false);
            flagSort(E, v.v1, v.v2, false);
            flagSort(E, v.v2 + 1, right, false);
        } else if(!dual) {
            // Only the white partition is not empty, partition it with double pivot
            flagSort(E, v.v1, v.v2, true);
        } // Last case: The only not-empty partition is white after partitioning with double pivot.
          // Description of the algorithm immediately implies that this consists of only one key value, thus is sorted.
    }
}
private static void flagSort(int[]E,int left,int right,boolean dual){
如果(左<右){//单例或空段已排序!
整数v;
if(dual)//最后一步只生成了一个白色分区。
//用双枢轴处理这个分区
v=分区(E,左,右,E[左],E[左];
否则//最后一步产生了多个分区,请正常进行。
v=分区(E,左,右,E[左],E[左+1]);
//分析分区
if((左!=v.v1)| |(右!=v.v2)){
//2或3个分区可用。进一步下降。
标志排序(E,左,v.v1-1,假);
flagSort(E,v.v1,v.v2,false);
flagSort(E,v.v2+1,右,假);
}如果(!dual){
//只有白色分区不是空的,用双枢轴分区
flagSort(E,v.v1,v.v2,true);
}//最后一种情况:使用双枢轴分区后,唯一一个非空分区为白色。
//对算法的描述立即意味着它只包含一个键值,因此被排序。
}
}
有人能帮忙创建一个更可读的版本吗

更多:这一款看起来更好:

private static void flagSort(int[] E, int left, int right, int offset){
    if(left < right) { // Singleton or empty segments are already sorted!
        IntTuple v = partition(E, left, right, E[left], E[left + offset]);
        // Analyze partitions
        if ((left != v.v1) || (right != v.v2)) {
            // 2 or 3 partitions available. Descend further.
            flagSort(E, left, v.v1 - 1, 1);
            flagSort(E, v.v1, v.v2, 1);
            flagSort(E, v.v2 + 1, right, 1);
        } else if (offset > 0)
            // Only the white partition is not empty, partition it with double pivot
            flagSort2(E, v.v1, v.v2, 0);
        // Last case: The only not-empty partition is white after partitioning with double pivot.
        // Description of the algorithm immediately implies that this consists of only one key value, thus is sorted.
    }
}
private static void flagSort(int[]E,int left,int right,int offset){
如果(左<右){//单例或空段已排序!
整数组v=分区(E,左,右,E[左],E[左+偏移];
//分析分区
if((左!=v.v1)| |(右!=v.v2)){
//2或3个分区可用。进一步下降。
标志排序(E,左,v.v1-1,1);
flagSort(E,v.v1,v.v2,1);
flagSort(E,v.v2+1,右,1);
}否则如果(偏移量>0)
//只有白色分区不是空的,用双枢轴分区
flagSort2(E,v.v1,v.v2,0);
//最后一种情况:使用双枢轴分区后,唯一一个非空分区是白色的。
//对算法的描述立即意味着它只包含一个键值,因此被排序。
}
}
特别感谢toto2,尽管我没有明确通过红/蓝测试

更多:更多的随机性,因为toto2同样完全有一点:

private static void flagSort(int[] E, int left, int right, int offset){
    if(left < right) {
        IntTuple v = partition(E, left, right, E[left + (offset % (right - left))], 
            E[left + ((2 * offset) % (right - left))]);
        if ((left != v.v1) || (right != v.v2)) {
            int random = rnd.nextInt(right - left);
            flagSort(E, left, v.v1 - 1, random);
            flagSort(E, v.v1, v.v2, random);
            flagSort(E, v.v2 + 1, right, random);
        } else if (offset > 0)
            flagSort(E, v.v1, v.v2, 0);
    }
}
private static void flagSort(int[]E,int left,int right,int offset){
if(左<右){
IntTuple v=分区(E,left,right,E[left+(偏移量%(right-left)),
E[左+((2*偏移量)%(右-左))];
if((左!=v.v1)| |(右!=v.v2)){
int random=rnd.nextInt(右-左);
标记排序(E,左,v.v1-1,随机);
标志排序(E、v.v1、v.v2、随机);
flagSort(E,v.v2+1,右,随机);
}否则如果(偏移量>0)
flagSort(E,v.v1,v.v2,0);
}
}

每次调用分区方法时,都会发生一件简单的事情: 蓝色和红色索引中的项目正是它们所属的位置。 因此,当您调用代码的这一部分时:

    flagSort(E, left, v.v1 - 1);
    flagSort(E, v.v1, v.v2);
    flagSort(E, v.v2 + 1, right);
这些呼叫不得包含蓝色和红色, 换句话说
 flagSort(E, left, v.v1 - 1);
 flagSort(E, v.v1 +1 , v.v2 -1);
 flagSort(E, v.v2 + 1, right);
IntTuple v = partition(E, left, right, rnd.nextInt(50), rnd.nextInt(50));