6370浏览
查看: 6370|回复: 1

【C语言算法连载4】三色旗

[复制链接]
本帖最后由 iooops 于 2016-4-6 04:18 编辑

【老掉牙系列之四】如果作为一个程序猿,你连这些都还不会,你就等着被叭!

【说明】

三色旗的问题最早由E.W.Dijkstra所提出,他所使用的用语为Dutch Nation Flag(Dijkstra为荷兰
人),而多数的作者则使用Three-Color Flag来称之。
假设有一条绳子,上面有红、白、蓝三种颜色的旗子,起初绳子上的旗子颜色并没有顺序,您
希望将之分类,并排列为红、白、蓝的顺序,要如何移动次数才会最少,注意您只能在绳子上
进行这个动作,而且一次只能调换两个旗子。

其实这是一个快速排序的算法。

好吧不理解题意的筒子打开下面这个链接:
http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Flag/

然后到
Three Colours版块


点go
然后就会出一个随机数,排好序啦。




觉得脑洞够大的筒子可以不看下面自行解决了。












好吧然后……

解决思路其实已经在链接里面被说明得很清楚了……

先来想办法把色列排成这样:
a[1..Lo-1] zeroes (red)
    a[Lo..Mid-] ones (white)
    a[Mid..Hi] unknown
    a[Hi+1..N] twos (blue)

然后再进行下面一步:
        Lo := 1; Mid := 1; Hi := N;
        while Mid <= Hi do
            Invariant: a[1..Lo-1]=0 and a[Lo..Mid-1]=1 and a[Hi+1..N]=2; a[Mid..Hi] are unknown.
            case a[Mid] in
                0: swap a[Lo] and a[Mid]; Lo++; Mid++
                1: Mid++
                2: swap a[Mid] and a[Hi]; Hi--

    --- Dutch National Flag Algorithm, or 3-way Partitioning ---

至于配套的图嘛,看链接里的图好啦。
楼主反正是看完图才终于理解了该算法的精髓的。





有兴趣的筒子可以把上述0、1、2排序的结果用C语言实现一下。对于大神理应是轻而易举。对于楼主小白要去好好在墙角思索一下敲出代码来
























那么三色旗的C语言实现代码如下(假设排列为BWR哈,至于排列为RWB,筒子们可以稍微改动一下哈):
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #define SWAP_FLAGS(x, y) { char temp; \
  5.                      temp = flags[x]; \
  6.                      flags[x] = flags[y]; \
  7.                      flags[y] = temp; }
  8. void printFlags(char* flags) {
  9.     int i;
  10.     for(i = 0; i < strlen(flags); i++) {
  11.         printf("%c ", flags[i]);
  12.     }
  13.     printf("\n");     
  14. }
  15. void adjust(char* flags) {
  16.     int w = 0;
  17.     int b = 0;
  18.     int r = strlen(flags) - 1;
  19.     while(flags[w] == 'B' && w < strlen(flags)) { b++; w++; }
  20.     while(flags[r] == 'R' && r > 0) { r--; }
  21.     while(w <= r) switch(flags[w]) {
  22.         case 'W':
  23.                w++;
  24.                break;
  25.         case 'B':
  26.                SWAP_FLAGS(b, w);
  27.                b++; w++;
  28.                break;
  29.         case 'R':
  30.                SWAP_FLAGS(r, w);
  31.                r--;
  32.     }
  33. }
  34. int main() {
  35.     char flags[] = {'R', 'W', 'B', 'W', 'W',
  36.                     'B', 'R', 'B', 'W', 'R', '\0'};
  37.     printFlags(flags);
  38.     adjust(flags);
  39.     printFlags(flags);
  40.     return 0;
  41. }
复制代码

输出结果如下:
R W B W W B R B W R
B B B W W W W R R R

好吧容我做一下代码的搬运工 - -
论数学的重要性 = =




刚刚提到排序0、1、2
楼主小白花了大概4个小时终于把上面的0、1、2能排出来了…………虽然还是参考了很多上述的代码,啊感觉还是要多多思索深入理解一下啊。
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. void adjust(int *a, int n) {
  4.         int x = 0;
  5.         int y = 0;
  6.         int z = n - 1;
  7.         printf("x %d y %d z %d\n", x, y, z);
  8.         printf("%d\n", a[x]);
  9.         while(a[y] == 0 && y < n) {
  10.                 x++;
  11.                 y++;
  12.                 printf("x %d y %d z %d\n", x, y, z);
  13.         }                                                                        //如果最左边是0的话,把0保留在最左边
  14.         while(a[z] == 2 && z > 0) {
  15.                 z--;
  16.                 printf("x %d y %d z %d\n", x, y, z);
  17.         }                                                                        //如果最右边是2的话,把2保留在最右边。
  18.                                                                                 //至此第一步完成,减少第二步的工作量,提高算法效率
  19.         while(y <= z) {
  20.                 switch(a[y]) {                //第二步开始,按照上面的思想
  21.                         case 0:
  22.                                 a[y] = a[y] + a[x] - (a[x] = a[y]);   
  23.                                 x++;
  24.                                 y++;
  25.                                 break;
  26.                                 printf("x %d y %d z %d\n", x, y, z);
  27.                         case 1:
  28.                                 y++;
  29.                                 break;
  30.                                 printf("x %d y %d z %d\n", x, y, z);
  31.                         case 2:
  32.                                 a[y] = a[y] + a[z] - (a[z] = a[y]);
  33.                                 z--;
  34.                                 printf("x %d y %d z %d\n", x, y, z);
  35.                 }
  36.         }                                                                        //至此第二步完成
  37.         int i;
  38.         for(i = 0; i < 6; i++) {
  39.                 printf("%d ", a[i]);
  40.         }
  41. }
  42. int main() {
  43.         int numbers[6] = {0, 2, 1, 0, 2, 1};        //我这里懒得生成随机数了 - -
  44.         int i;
  45.         adjust(numbers, 6);
  46.         printf("\nsorted numbers are \n");
  47.         for(i = 0; i < 6; i++) {
  48.                 printf("%d ", numbers[i]);
  49.         }
  50.         return 0;
  51. }
复制代码


好吧虽然楼主觉得对于数字而言,会有比这更高效的排序算法的。
啊终于可以去睡觉啦!!!!!




参考:
http://www.openhome.cc/Gossip/AlgorithmGossip/ThreeColorsFlags.htm
http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Flag/




dsweiliang  初级技神

发表于 2016-4-7 08:23:48

沙发
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail