算法初级课随笔(2.1):荷兰国旗问题、改进版快速排序

戒邪淫,心地光明
引以为戒,切莫邪淫

一.荷兰国旗问题

给定一个数组arr,和一个数num,请把小于num的数放在数组的
左边,等于num的数放在数组的中间,大于num的数放在数组的
右边。

荷兰最早采用横条三色旗
  • 思路就是:
    1.开始时先设一个变量cur,用来指向当前分量。
    less与more分别用来表示“小于区”、“大于区”的“范围 位置”。less在-1处,more在arr.length处


    起始

    2.开始遍历。若cur指向的数小于num,将此数与 “小于区” 的下一个数位置交换(4移动到0位置,即位置没变)。 接着cur++;less++“小于区”扩大。


    分量比num小的情况

    3.cur指向的值为5,与num相等。这时直接cur++跳往下一个分量,相当于5在 “等于区”。
    分量等于num的情况

    4.此时,cur指向的数为9,比num大。这时将cur指向的数9与 “大于区”的前一个数交换位置。 more--,大于区扩大;
    因为从右侧而来的数的值不好确定,所以curr不变,需要再次判断移过来的数值大小并进行相应操作。
    分量大于num的情况

    5.接下来判断出cur所指的值是6依然大于num,与“大于区”前一个数 1 交换位置,more--“大于区”扩大。
    cur不变继续判断,1被交换至此,小于num。则 1 与“小于区”后一个数5交换位置,less++,cur++。


    操作后cur不变再次判断的情况

    6.最后呢,在cur==more时,递归结束。(没有“大于区”时也是如此)
    结束

二.经典快速排序

在写改进版快排前,先复习一下经典快速排序
快速排序需要划分成这两个区域

1.这里将数组的最后一个位置的数作为 “划分值”并移出。
2.“右拆左补”:left++从左向右扫描,遇到比“划分值”大的数,就把它移到空缺处;
“左拆右补”:接着right- -向左扫描,碰到比小于等于“划分值”的数就移到左边的空缺处。


挖坑填数

3.在left==right时,将划分值放入left或right位置 。并将其两侧的元素继续以此方式排序。
分而治之
三.改进快速排序
  • 在上图在第一次排序后,“分而治之”之前,左侧被划分区域还有一个“6”呢。若是将小于还有大于“6”的区域的数拿出去继续递归,等于“6”的部分不要动,是不是会好一些?

  • 所以经典快速排序有一个缺点,就是每次排序只能确定好一个数,效率会比较低;

  • 如何改造呢:根据前面提到的荷兰国旗问题, 在快速排序中增加一个“=X”区域

  • 步骤简述:
    1.变量cur表示当前指向的数组元素。变量less与more分别代表大于区小于区的“位置 范围”
    将数组的最后一个元素值设为“划分值”。并暂归入“大于区”中。


    q2.png

    2.元素4被纳为小于区;经过两个相同的划分值元素后,cur所指的值大于“6”,所以要与“大于区”前一个分量交换。


    q3.png
q4.png

3.再次当前判断cur所指元素的值并继续。


q5.png

4.终止条件是 cur==more。返回“等于区”的范围是:less+1more
接着两侧区域的数组重复相同操作,最终得到有序数组。

q6.png

  • 代码实现
/**
*  改进版快速排序代码
*/
public static void quickSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        quickSort(arr, 0, arr.length - 1);
    }



    public static void quickSort(int[] arr, int L, int R) {
        if (L < R) {
            int[] p = partition(arr, L, R);
            quickSort(arr, L, p[0] - 1);  //p[0]不属于"小于区"
            quickSort(arr, p[1] + 1, R);  //p[1]不属于"大于区"
        }
    }

    //返回一个存有"等于区域"的下标的数组
    public static int[] partition(int[] arr, int L, int R) {
        int less = L - 1;  
        int more = R;   //将最后一个数作为划分值
        int cur = L;
        while (cur < more) {
    
            if (arr[cur] < arr[R]) {
                swap(arr, ++less, cur++);
          //++less表示在交换元素时指向“小于区”的下一个数,
         //cur++表示交换完成后指向下一个数组元素
  
            } else if (arr[cur] > arr[R]) {
                swap(arr, --more, cur);
          //cur不动,将继续判断其所指向的值
    
            } else {  //当前值等于判定值
                cur++;  
            }
        }
        swap(arr, more, R); //将判定值放入“等于区域”中
        return new int[] { less + 1, more };
    }

  //实现数组分量的交换
    public static void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,780评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,424评论 1 305
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,397评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,576评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,997评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,945评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,107评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,850评论 0 208
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,625评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,804评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,285评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,613评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,291评论 3 242
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,164评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,963评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,096评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,886评论 2 278

推荐阅读更多精彩内容

  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 4,875评论 0 9
  • 目录 荷兰国旗问题 随机快排 堆排序 排序算法的稳定性及其汇总 工程中的综合排序算法 比较器的使用 桶排序、计数排...
    管弦_阅读 450评论 0 0
  • 翻译界一奇葩 骗子保定诺华(译华)翻译公司孙爱宏现形记 题记:读完本书,您将会知道谁是翻译界最不要脸的骗子,她是如...
    斯拉夫的脚印阅读 339评论 0 0
  • 正文
    九点九分听见回想阅读 108评论 0 0
  • 天已接近全黑,但这是个有晚霞的黄昏。一个劳累了一天的农夫扛着农具,牵着他的那匹老马埋头走在回家的路上。他是三个孩子...
    萧萧Ruth阅读 143评论 0 0