快速排序

递归实现

$arr = [2,3,4,9,1,20,12,12,1,2];

function quickSort($arr){

    if(count($arr)<=1){
        return $arr;
    }

    $left_array= $right_array = [];
    $rand = (rand(0,count($arr)-1));//随机索引

    $pos = $arr[$rand ];//需要做比较的值

    unset($arr[$rand]);//将该值从原数组去掉

    foreach($arr as $k => $v){

        if($v<$pos){
            $left_array[] = $v;
        }else{
            $right_array[] = $v;
        }
    }
    
    $left_array = quickSort($left_array);  
    $right_array = quickSort($right_array);  

    //合并 
    return array_merge($left_array, array($pos), $right_array);  


}
echo '<pre/>';
print_r(quickSort($arr));

时间复杂度是nlogn.

上面的例子有个问题 $left_array$right_array都需要开启额外的空间来存储排序后的数据,所以这种方式的快排并不是原地排序.

问题来了,那什么是原地排序呢?

原地排序就是除了数据本身存储的空间外,并不需要其他空间.
像上面的例子,就是不需要$left_array$right_array来存储排序后的数据.

这样子,编程的复杂度就提高了,那要怎么操作呢?

这里我用java代码来说明快排的原地排序,并花时间画了几幅图来帮助理解.


上面的图中有7个骷髅,最高的210cm,最矮的140cm,现在我们要把它们从矮到高进行排序.思路如下:

  1. 将最后一个骷髅作为基准骷髅,从第一个骷髅开始和它比较高矮,矮的放左边,高的放右边.
  2. 这样第一轮排序后,已经保证了左边的都比右边矮,但是左边区间里并不是有序的,需要重复刚才的操作.右边同理.
  3. 这样处理n次后,才能保证排序完成.

那怎么用原地排序的方式来操作呢?

关键就是利用额外的标识变量.这里我用标识变量i当做已经比较高矮后的骷髅下标的下一个骷髅,这里可能有点绕,就是说{}区域内的骷髅是A[0]A[i-1]的元素,当i=0的时候,不存在A[0]A[-1]的区间,所以就是空的.
i=1的时候,A[0]~A[0]即第一个元素是已经排序好后的骷髅.
i=2的时候,A[0]~A[1]即前面两个元素是已经排序好后的骷髅.

标识j当做未比较的骷髅下标.

刚开始,没比较之前,左边{}区域放的就是比基准骷髅矮的骷髅.在这里,基准骷髅是175cm,所以{}标识的区域应该放的都是<=175cm的骷髅.

第一次拿j=0的骷髅和pivot比较,发现210>175,比pivot高,不需要将它移动到{}里,那么i不变,j++.

第二次拿j=1的骷髅和pivot比较,发现150<=175,比pivot矮,要将它移动到{}里,怎么移呢,将150和210交换位置.这时候,{}里已经有1个元素了,i++,j++.

第三次拿j=2的骷髅和pivot比较,发现170<=175,比pivot矮,要将它移动到{}里,将170和210交换位置,这时候{}里已经有2个元素,i++,j++.

第四次比较

第五次比较

第六次比较

最后

这样子,就保证了{}里的都是比175矮的骷髅,高的都在右边.

接下来就是要对{}的数据和右边的数据再次执行相同的逻辑就可以实现全局排序了.

看看代码怎么写

package cn.test;

import java.util.Arrays;

/**
 * @author Administrator
 */
public class QuickSort {

    public static void main(String[] args) {
        int[] data = {210, 150, 170, 175, 140, 190, 175};
        quickSort(data, 0, data.length - 1);
        System.out.println(Arrays.toString(data));
    }

    private static void quickSort(int[] data, int p, int r) {
        if (p >= r) {
            return;
        }
        //找到基准元素
        int q = partition(data, p, r);
        quickSort(data, p, q - 1);
        quickSort(data, q + 1, r);
    }

    private static int partition(int[] data, int p, int r) {
        int i = p;
        int j = p;
        int pivot = data[r];
        while (j < r) {
            if (data[j] <= pivot) {
                int tmp = data[i];
                data[i] = data[j];
                data[j] = tmp;
                i++;
            }
            j++;
        }
        int tmp = data[i];
        data[r] = tmp;
        data[i] = pivot;
        return i;
    }
}

需要注意,快排并不是稳定排序, 每次排序后,值相同的元素不能确保先后顺序.

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

推荐阅读更多精彩内容

  • 电影《驴得水》,一开始,我就被它温暖利落的画面,活泼欢快的电影配乐,和轻松幽默的开场吸引了。 一群城市教师,因为怀...
    吴小鲤儿阅读 1,013评论 1 0
  • 今天换个风格,如下思维导图: 跑步, 看起来体力活, 用起来脑力活。 跑起来是双脚, 享受的是身心。 耗尽的是体力...
    玉儿说阅读 255评论 6 5
  • 那个残旧的老屋外榕树下不再瑶琴随红影那个郁闷烦躁的夏天雨总是下个不停栀子花静俏俏闭着羞答答的眼鞋子里懒洋洋地躺着一...
    弋夫阅读 165评论 0 0