快速排序深入之荷兰国旗问题

一、序言

  在使用partition-exchange排序算法时,如快速排序算法(即使选择了一个好的关键元素pivot values),我们往往面临一个很尴尬的境地--当排序对象中有很多重复的元素,partition-exchange排序算法表现很不尽如人意。当所有元素都相等时,这就特别容易理解了。在每次递归中,左边部分是空的(没有元素比关键元素小),而右边部分只能一个一个递减移动。结果导致耗费了二次方时间来排序相等元素。为了解决这个问题(有时叫做荷兰国旗问题),我们详细介绍下解决这个问题的方法。

二、”荷兰国旗难题“问题描述

  ”荷兰国旗难题“是计算机科学中的一个程序难题,它是由Edsger Dijkstra提出的。荷兰国旗是由红、白、蓝三色组成的。

  现在有若干个红、白、蓝三种颜色的球随机排列成一条直线。现在我们的任务是把这些球按照红、白、蓝排序。

三、问题分析

  

这个问题我们可以将这个问题视为一个数组排序问题,这个数组分为前部,中部和后部三个部分,每一个元素(红白蓝分别对应0、1、2)必属于其中之一。由于红、白、蓝三色小球数量并不一定相同,所以这个三个区域不一定是等分的,也就是说如果我们将整个区域放在[0,1]的区域里,由于三色小球之间数量的比不同(此处假设1:2:2),可能前部为[0,0.2),中部为[0.2,0.6),后部为[0.6,1]。我们的思路如下:将前部和后部各排在数组的前边和后边,中部自然就排好了。具体的:
设置两个标志位begin和end分别指向这个数组的开始和末尾,然后用一个标志位current从头开始进行遍历:
1)若遍历到的位置为0,则说明它一定属于前部,于是就和begin位置进行交换,然后current向前进,begin也向前进(表示前边的已经都排好了)。
2)若遍历到的位置为1,则说明它一定属于中部,根据总思路,中部的我们都不动,然后current向前进。
3)若遍历到的位置为2,则说明它一定属于后部,于是就和end位置进行交换,由于交换完毕后current指向的可能是属于前部的,若此时current前进则会导致该位置不能被交换到前部,所以此时current不前进。而同1),end向后退1。

四、实现代码

  1、伪代码:

    伪代码使用A代表元素数组

  

procedure three-way-partition(A : array of value, mid : value):
    i ← 0
    j ← 0
    n ← size of A - 1

    while j ≤ n:
        if A[j] < mid:
            swap A[i] and A[j]
            i ← i + 1
            j ← j + 1
        else if A[j] > mid:
            swap A[j] and A[n]
            n ← n - 1
        else:
            j ← j + 1

  2、java代码实现:

  

public void sort(List<Integer> list){
        int size = list.size();
        int topEnd = 0;
        int bottomStart = size - 1;
        int current = 0;
        while(current <= bottomStart){
            int currentVal = list.get(current);
            if(currentVal < 1){
                swap(list, current, topEnd);
                topEnd++;
                current++;
            }else if(currentVal > 1){
                swap(list, current, bottomStart);
                bottomStart--;
            }else{
                current++;
            }
        }
    }

五、参考文献:

  http://en.wikipedia.org/wiki/Dutch_national_flag_problem

  http://en.wikipedia.org/wiki/Quicksort

  算法习作--荷兰国旗问题

  

时间: 2024-10-02 20:11:59

快速排序深入之荷兰国旗问题的相关文章

八大基本排序---快速排序(荷兰国旗问题)

引言: 解答: 需要准备3个下标 如果当前数字=num,cur跳下一个 如果数组中的当前数字<num,把这个数(3)和小于区域的下一个数(5)交换 然后小于区域扩一下 然后cur跳下一个位置 数组中的当前数字<num,把这个数(2)和小于区域的下一个数(5)交换, 然后小于区域扩一下 然后cur跳下一个位置 PS: 如果一上来遇到的就是cur<num 把这个数(3)和小于等于区域的下一个数(3)交换[自己和自己交换] 数组中的当前数字>num,把这个数(7)和大于区域的前一个数(x

荷兰国旗问题:

何谓荷兰国旗: 现有红.白.蓝三个不同颜色的小球,乱序排列在一起,请重新排列这些小球,使得红白蓝三色的同颜色的球在一起.这个问题之所以叫荷兰国旗,是因为我们可以将红白蓝三色小球想象成条状物,有序排列后正好组成荷兰国旗. 问题转换为:给定数组A[0…N-1],元素只能取0.1.2三个值,设计算法,使得数组排列成“00…0011…1122…22”的形式. 借鉴快速排序中partition的过程.定义三个指针:begin=0.current=0.end=N-1: A[cur]==2,则A[cur] 与

荷兰国旗 Flag of the Kingdom of the Netherlands

问题描述:现有n个红白蓝三种不同颜色的小球,乱序排列在一起,请通过两两交换任意两个球,使得从左至右的球依次为红球.白球.蓝球.这个问题之所以叫做荷兰国旗,是因为将红白蓝三色的小球弄成条状物,并有序排列后正好组成荷兰国旗. 解题方法1:蛮力求解 解题方法2:为了讨论方便用数字0表示红色球,用数字1表示白色球,用数字2表示蓝色球,所以最后的排序就是0...1...2... 快速排序基于划分过程,选取主元间整个数组划分为两个子数组.是否可以借鉴划分过程设定三个指针完成一次遍历完成重新排列,使得所有的球

荷兰国旗

题目描述 拿破仑席卷欧洲大陆之后,代表自由,平等,博爱的竖色三色旗也风靡一时.荷兰国旗就是一面三色旗(只不过是横向的),自上而下为红白蓝三色. 该问题本身是关于三色球排序和分类的,由荷兰科学家Dijkstra提出.由于问题中的三色小球有序排列后正好分为三类,Dijkstra就想象成他母国的国旗,于是问题也就被命名为荷兰旗问题(Dutch National Flag Problem). 下面是问题的正规描述: 现有n个红白蓝三种不同颜色的小球,乱序排列在一起,请通过两两交换任意两个球,使得从左至右

编程之法:面试和算法心得(荷兰国旗)

内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 拿破仑席卷欧洲大陆之后,代表自由,平等,博爱的竖色三色旗也风靡一时.荷兰国旗就是一面三色旗(只不过是横向的),自上而下为红白蓝三色. 该问题本身是关于三色球排序和分类的,由荷兰科学家Dijkstra提出.由于问题中的三色小球有序排列后正好分为三类,Dijkstra就想象成他母国的国旗,于是问题也就被命名为荷兰旗问题(Dutch National Flag Problem). 下面是问题的正规描述: 现有n个红白蓝

荷兰国旗问题

荷兰国旗问题: 现有红,白,蓝三个不同颜色的小球,乱序排列在一起,重新排列这些小球,使得红白蓝三色的同颜色的球在一起. 问题分析: 问题转换为:给定数组A[0,1,...,N-1],元素只能取0,1,2三个值,设计算法使得数组重新排列成“000...111..222”的形式. 可以使用三个游标,begin=0,cur=0,end=N-1. 程序实现: 1 /*************************************** 2 FileName HollandFlag.cpp 3 A

荷兰国旗问题 划分成3部分 leecode

1 public class Solution { 2 public void sortColors(int[] A) { 3 int len=A.length; 4 int beg=0; 5 int end=len-1; 6 int cur=0; 7 while(cur<=end){ 8 if(A[cur]==0) 9 { 10 swap(A,cur,beg); 11 beg++; 12 cur++; 13 14 15 } 16 else if(A[cur]==1) 17 { 18 cur++

NYOJ_268_荷兰国旗问题

荷兰国旗问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:1 描写叙述 荷兰国旗有三横条块构成,自上到下的三条块颜色依次为红.白.蓝.现有若干由红.白.蓝三种颜色的条块序列.要将它们又一次排列使全部同样颜色的条块在一起.本问题要求将全部红色的条块放最左边.全部白色的条块放中间.全部蓝色的条块放最右边. 输入 第1行是一个正整数n(n<100),表示有n组測试数据.接下来有n行,每行有若干个由R,W,B三种字符构成的字符串序列,当中R,W和B分别表示红.白.蓝三种颜色的条块

[算法系列之十一]荷兰国旗问题

[问题] 现有红白蓝三个不同颜色的小球,乱序排列在一起,请重新排列这些小球,使得红白蓝三色的同颜色的球在一起.这个问题之所以叫荷兰国旗问题,是因为我们可以将红白蓝三色小球想象成条状物,有序排列后正好组成荷兰国旗. [分析] 这个问题我们可以将这个问题视为一个数组排序问题.红白蓝分别对应数字0.1.2.红.白.蓝三色小球数量并不一定相同. [思路一] First, iterate the array counting number of 0's, 1's, and 2's, then overwr