一排木桶里分别装有红白蓝三色小球(分别用0,1,2表示),如何让所有的'0'出现在前面,所有的'1'在中间,所有的'2'在最后。
要求:要求空间复杂度为O(1),只许遍历一遍字符串数组。
之所以叫荷兰国旗,是因为我们可以将红白蓝三色小球想象成条状物,有序排列后正好组成荷兰国旗。
该算法的精髓在于把元素分为3个区域,只需扫描一次,通过交换元素,就能把元素放到该去的区域。
要求:要求空间复杂度为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++;
}
}
}