荷兰国旗问题

/**
 * 荷兰国旗问题
 * 解题的基本策略:变了两个颜色区域,如果颜色条不属于所在的区域,则交换一个属于该
 * 区域的颜色条。每一次都是必要的交换,从而实现最小交换次数。
*/

#include <iostream>
using namespace std;

const int N		  = 100;
int		 flag[N];	// 国旗颜色条数组
int		 pre[N];		// 记录该红条的前红条位置
int		 split1;		// 区域分隔1
int		 split2;		// 区域分隔2
int		 blue_red;  // 红条在蓝色区域的标记
int		 white_red; // 红条在白色区域的标记
int		 counts = 0;

// print
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(0 != flag[i]) {					// 如果不属于该区域
			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(int i = split1; i < split2; i++) {
		if(1 != flag[i]) {
			while(2 == flag[b]) { b--; }
			swap(flag[i], flag[b]);
			b--;
		}
	}
}

// initialize
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(0 == flag[i]) {
			red_num++;
			pre[i] = preI;
			preI   = i;
		} else if(1 == flag[i]) {
				white_num++;
		}
	}
		
	// 将国旗分成三个颜色区域
	// 0~split1-1(red), split1~split2-1(white), split2~N-1(blue)
	split1	= red_num;
	split2	= red_num + white_num;
	blue_red = preI;
	int	 i = split2 - 1;
	while(0 != flag[i]) { i--; }
	white_red = i;	
}

int main() {
	init();
	cout << "原始:" << endl;
	out();
	work();
	cout << "移动" << counts << "次:" << endl;
	out();

	return 0;
}
转自左飞《CPP数据结构原理与经典问题求解》
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值