荷兰国旗算法及其拓展

来源:互联网 发布:如何找到电子称软件 编辑:程序博客网 时间:2024/04/20 12:42
一排木桶里分别装有红白蓝三色小球(分别用0,1,2表示),如何让所有的'0'出现在前面,所有的'1'在中间,所有的'2'在最后。
要求:要求空间复杂度为O(1),只许遍历一遍字符串数组。 
之所以叫荷兰国旗,是因为我们可以将红白蓝三色小球想象成条状物,有序排列后正好组成荷兰国旗。
该算法的精髓在于把元素分为3个区域,只需扫描一次,通过交换元素,就能把元素放到该去的区域。 

我们可以把该算法扩展到将COLORNUM个不同颜色的小球(数字)按顺序归类,只需要不断地把左右边界往中间移动就行。 

#include <iostream>#include <cstdlib>using namespace std;void Sort(int lib[], int libLen, int color[], int colorLen);void TheDutchFlag(int lib[], int &left, int &right, int min, int max);void Swap(int &a, int &b);int main(){const int COLORNUM = 19;int color[COLORNUM] = {0};for (int i=0; i<COLORNUM; i++) //为不同颜色赋值 {color[i] = i;}const int MAXSIZE = 140;int lib[MAXSIZE] = {0};for (int i=0; i<MAXSIZE; i++){lib[i] = rand() % COLORNUM;}for (int i=0; i<MAXSIZE; i++){cout << lib[i] << " ";}cout << endl;   Sort(lib, MAXSIZE, color, COLORNUM);for (int i=0; i<MAXSIZE; i++){cout << lib[i] << " ";}cout << endl;        return 0;}void Swap(int &a, int &b){int temp = a;a = b;b = temp;}void Sort(int lib[], int libLen, int color[], int colorLen)//将COLORNUM个不同颜色的小球(数字)按顺序归类{int left = 0;int right = libLen - 1;int min = 0;int max = colorLen - 1;while (min < max && left < right){if (min == max - 1) //只有两个不同元素,直接交换即可{while (left < right){while (lib[left] == color[min]) //确定左边界的位置 {left++;}while (lib[right] == color[max]) //确定右边界的位置 {right--;}if (left < right){Swap(lib[left++], lib[right--]);}}} else //有超过2个不同元素,先把最大值和最小值分别放到左右区域,其他元素放在中间区域 {TheDutchFlag(lib, left, right, color[min], color[max]);}//处理中间的区域的元素,重新设置最大值和最小值 min++;max--;}}void TheDutchFlag(int lib[], int &left, int &right, int min, int max){while (lib[left] == min) //确定左边界的位置 {left++;}while (lib[right] == max) //确定右边界的位置 {right--;}int i = left;while (i <= right){if (lib[i] == min) //是最小值,则与左区域的元素交换,同时左边界右移,游标也右移 {Swap(lib[i++], lib[left++]);}else if (lib[i] == max) //是最大值,则与右区域的元素交换,同时右边界左移,游标不动 {Swap(lib[i], lib[right--]);}else //既不是最大值也不是最小值,则该元素属于中间区域,不做任何交换,游标右移 {i++;}}}


0 0