三色旗算法

来源:互联网 发布:大道行知传媒官方网站 编辑:程序博客网 时间:2024/05/01 12:47
算法描述:
三色旗的问题最早由E.W.Dijkstra所提出,他所使用的用语为Dutch Nation Flag(Dijkstra为荷兰人),而多数的作者则使用Three-Color Flag来称之。

假设有一条绳子,上面有红、白、蓝三种颜色的旗子,起初绳子上的旗子颜色并没有顺序,您希望将之分类,并排列为蓝、白、红的顺序,要如何移动次数才会最少,注意您只能在绳子上进行这个动作,而且一次只能调换两个旗子。示意图:


 
解法:

在一条绳子上移动,在程式中也就意味只能使用一个阵列,而不使用其它的阵列来作辅助,问题的解法很简单,您可以自己想像一下在移动旗子,从绳子开头进行,遇到蓝色往前移,遇到白色留在中间,遇到红色往后移。


 
只是要让移动次数最少的话,就要有些技巧:
  如果图中w所在的位置为白色,则w+1,表示未处理的部份移至至白色群组。
  如果w部份为蓝色,则b与w的元素对调,而b与w必须各+1,表示两个群组都多了一个元素。
  如果w所在的位置是红色,则将w与r交换,但r要减1,表示未处理的部份减1。
 
注意的细节:
第一,当w指向的是红色而和r交换时,如果此时r指向的是红色,显然没有必要把两个红色的旗子交换。所以这时应该把r前移,直到r指向的不是红色的时候才和w指向的旗子交换。当然移动时必须确保w<r。  
第二,同样地,当w指向的是蓝色而要和b的指向交换时,如果b指向的不是蓝色,则交换。否则如果b指向的是蓝色,则也没有必要把两个蓝色的旗子交换。所以这时应该把b和w都往后移一位。


注意b、w、r并不是三色旗的个数,它们只是一个移动的指针;什幺时候移动结束呢?一开始时未处理的r指针处于最后一个旗子位子,当r的索引数减至少于w的索引数时,表示接下来的旗子就都是红色了,此时就可以结束移动。

Java 代码实现:

    public static void main(String[] args) {    char[] threeFlag = new char[]{'R','B','R','W','R','R','W','B','B','W'};    int bPointer = 0;    int wPointer = 0;    int rPointer = threeFlag.length - 1;    printProcess(threeFlag, bPointer, wPointer, rPointer);    while (wPointer < rPointer) {    if (threeFlag[wPointer] == 'B') {    char temp = threeFlag[bPointer];    threeFlag[bPointer] = threeFlag[wPointer];    threeFlag[wPointer] = temp;    bPointer++;    wPointer++;    } else if (threeFlag[wPointer] == 'W') {    wPointer++;    } else if (threeFlag[wPointer] == 'R') {    char temp = threeFlag[rPointer];    threeFlag[rPointer] = threeFlag[wPointer];    threeFlag[wPointer] = temp;    rPointer--;    }    printProcess(threeFlag, bPointer, wPointer, rPointer);    }    }    public static void printProcess(char[] threeFlag, int bPointer, int wPointer, int rPointer) {    char arrow = '↓';    String space1 = " ";    String space2 = "  ";    String space3 = "   ";    String s1 = "";    String s2 = "";    for (int i=0; i<threeFlag.length; i++) {    if ((bPointer == wPointer) && (bPointer==i)) {    s1 = s1 + "bw" + space1;    s2 = s2 + arrow + arrow + space1;    } else if ((wPointer == rPointer) && (wPointer==i)) {    s1 = s1 + "wr" + space1;    s2 = s2 + arrow + arrow + space1;    } else {    if (bPointer == i) {    s1 = s1 + "b" + space2;    s2 = s2 + arrow + space2;    } else if (wPointer == i) {    s1 = s1 + "w" + space2;    s2 = s2 + arrow + space2;    } else if (rPointer == i) {    s1 = s1 + "r" + space2;    s2 = s2 + arrow + space2;    } else {    s1 = s1 + space3;    s2 = s2 + space3;        }    }    }    String s3 = "";    String s4 = "";    String split = "---";    for (int i=0;i<threeFlag.length;i++) {    s3 = s3 + threeFlag[i] + space2;    s4 = s4 + split;    }    System.out.println(s1);    System.out.println(s2);    System.out.println(s3);    System.out.println(s4);    }

运行结果:


0 0
原创粉丝点击