排序相关——荷兰国旗问题

来源:互联网 发布:oracle数据库导出 编辑:程序博客网 时间:2024/05/01 15:23


给定一个数组,它包括0,1,2三种数,如何做到0放到数组的左边,1放到数组的中间,2放到数组的右边。要求使用交换、原地排序,而不是利用计数进行排序。

这个问题其实就是荷兰国旗问题:

现有n个红白蓝三种不同颜色的小球,乱序排列在一起,请通过两两交换任意两个球,使得从左至右的球依次为红球、白球、蓝球。这个问题之所以叫荷兰国旗,是因为将红白蓝三色的小球弄成条状物,并有序排列后正好组成荷兰国旗。





思路:设定三个用于指定元素的下标指针(PS:在Java中没有指针,此处方便描述):一个前指针begin,一个中指针current,一个后指针end。Current指针遍历整个数组序列:


(1)当current指针所指元素为0时,与begin指针所指的元素交换,而后current++,begin++;


(2)当current指针所指元素为1时,不做任何交换,而后current++;


(3)当current指针所指元素为2时,与end指针所指的元素交换,而后current指针不动,end--.    为什么current指针不动,因为end指针所指的元素在交换前还没有遍历,所以交换后current还是需要停留在当前位置,判断这个交换过来的数是0还是1还是2.


(4)当current指针与end指针重合,遍历结束。


public class HollandFlagProblem {public static void main(String[] args) {// TODO Auto-generated method stubint[] arr={1,1,0,0,2,1,1,0};//int[] arr={0,1,2,0,1,2,0};colorSort(arr);for(int i=0;i<arr.length;i++){System.out.println(arr[i]);}}public static void colorSort(int[] arr){if(arr==null||arr.length==0)return;int begin=0;int current=0;int end=arr.length-1;while(current<=end){if(arr[current]==1)current++;else if(arr[current]==0){swap(arr,begin,current);begin++;current++;}else if(arr[current]==2){  swap(arr,end,current);end--;  //需要注意的是交换后,当前指针位置不变}}}public static void swap(int[] arr, int a, int b){int temp=arr[a];arr[a]=arr[b];arr[b]=temp;}}