荷兰国旗问题

        荷兰的国旗由红色、白色和蓝色3种颜色组成。现在假设有很多这3种颜色的线被存放在一个数组里,要求每次操作仅能进行一次交换,在原数组的基础上操作。待对数组进行一遍扫描后,3种颜色自然分开,颜色顺序为红、白、蓝。另外,要求在O(n)的复杂度下,是移动次数最少。

//荷兰国旗问题
#include <iostream>
#include <cstdlib>
using namespace std;


const int N = 100;
int flag[N];//存放颜色数组
int pre[N];//记录红色位置数组
int split1; //红色和白色的分割点
int split2;//白色和蓝色的分割点
int red_blue; //红色在蓝色区域的部分
int red_white;//红色在白色区域的部分
int counts = 0;//记录交换次数

void print();//输出
void swap(int & x,int & y);//交换
void fun();//实现
void init();//初始化

int main()
{
    init();
    cout<<"原始: "<<endl;
    print();
    fun();
    cout<<"移动"<<counts<<"次"<<endl;
    print();
    return 0;
}

void print()
{
    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 fun()
{
    for (int i = 0; i < split1; i++)//交换红色与非红色部分
    {
        if (flag[i] != 0)
        {
            if (red_blue >= split2)
            {
                swap(flag[i],flag[red_blue]);
                red_blue = pre[red_blue];
            }
            else
            {
                swap(flag[i],flag[red_white]);
                red_white = pre[red_white];
            }

        }
    }
    int b = N - 1;
    for (int j = split1; j < split2; j++)//排序白色和蓝色
    {
        if (flag[j] != 1)
        {
            while(flag[b] == 2)
            {
                b--;
            }
            swap(flag[j],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++;
        }
    }

    split1 = red_num;
    split2 = red_num + white_num;
    red_blue = preI;
    int j = split2 - 1;
    while(flag[j] != 0)
    {
        j--;
    }
    red_white = j;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值