• 荷兰国旗问题


    荷兰国旗问题

        上方的图片便是一个荷兰国旗,从图中我们可以很清楚的看出它的特点,它有三个区域组成,即红,白,蓝。

    好,现在我们的问题出来了。现在我们面前有一张桌子,桌子上整齐的摆放着红色,白色,蓝色三种线条,但他们的顺序是凌乱的。

    要求是:用一个算法把这些线条挑出来重新摆放顺序,最后的结果就像上图的荷兰国旗,红色在上,白色在中间,蓝色在最下面。

    另外,要求在O(n)的复杂度下,使移动次数最少。

    算法分析如下:

        荷兰国旗问题其实是一个排序问题。可以将红,白,蓝3种颜色分别用数字0、1和2表示,并使用一个数组来存储它们。将相同颜色

    的线条归为一类就相当于将数组中的数组按大小进行排序,只不过数组里存储的数值只有3种而已。其解题的基本策略是遍历两个颜色区域,

    如果颜色条不属于所在区域,则交换一个属于该区域的颜色条。这样,每一次都是必要的交换,从而实现最少交换次数。

    代码如下:

    #include <iostream>
    using namespace std;
    const int N=10;
    int flag[N];  //国旗颜色条数组
    int pre[N];   //记录该白条的前白条位置
    int split1;   //区域分割1
    int split2;   //区域分割2
    int blue_red; //红条在蓝色区域的标记
    int white_red; //红条在白色区域的标记
    int counts = 0;

    void out()
    {
     for (int i=0;i<N;i++)
     {
      cout<<flag[i];
     }
     cout<<endl;
    }

    void swap(int& x,int& y)
    {
     int temp=x;
     x=y;
     y=temp;

     counts++;
    }

    void work()
    {
     for (int i=0;i<split1;i++)   //红色区域:交换非红条
     {
      if (flag[i]!=0)     //如果不属于该区域
      {
       if(blue_red>=split2)
       {
         swap(flag[i],flag[blue_red]);
         blue_red = pre[blue_red];
       }
       else{
        swap(flag[i],flag[white_red]);
        white_red = pre[white_red];
       }
      }
     }
     int  b=N-1;  //白、蓝区域
     for ( i=split1;i<split2;i++)
     {
      if (flag[i] != 1)
      {
       while (flag[b]==2) b--;
       swap(flag[i],flag[b]);
       b--;
      }
     }
    }

    //初始化
    void init()
    {
     int red_num = 0;  //统计红色条数
     int white_num = 0; //统计白色条数
     int preI = -1;
     for (int i=0;i<N;i++)
     {
      flag[i] = rand()%3;
      if (flag[i]==0)
      {
       red_num++;
       pre[i] = preI;
       preI=i;
      }
      else
       if (flag[i]==1)
       {
        white_num++;
       }
     }
       
     //将国旗分成3个颜色区域:
     //0~split-1(红),split1~split2-1(白),split2~N-1(蓝)
     split1=red_num;
     split2=red_num+white_num;
     blue_red=preI;
     i=split2-1;
     while (flag[i] !=0) i--;
     white_red = i;
    }

    int main()
    {
     init();
     cout<<"原始:"<<endl;
     out();

     work();
     cout<<"移动"<<counts<<"次:"<<endl;
     out();

     return 0;

    }

  • 相关阅读:
    二维数组
    快速排序
    冒泡排序2
    对char类型数组的英文字母进行冒泡排序
    对char类型的数组进行冒泡排序
    冒泡排序
    对数组随机赋值,并输出(Arrays.toString(arr))
    数组声明的几种方式以及length属性
    猜拳游戏二
    二维小波包重构wprec2wprcoef
  • 原文地址:https://www.cnblogs.com/fuyanan/p/3014676.html
Copyright © 2020-2023  润新知