快速排序

作者: 囧囧有神2号 | 来源:发表于2017-08-15 17:05 被阅读0次

快速排序是一种分治的排序算法,它将一个数组分解成两个子数组,将两部分独立的排序。快速排序与归并排序是互补的:归并排序将数组分成两个子数组分别排序,并将有序的数组归并,已将整个数组排序;而快速排序将数组排序的方式是当两个数组都有序时整个数组自然就有序了。第一种情况递归调用发生在整个数组之前,第二种情况递归发生在处理数组之后。在归并排序中一个数组被等分成两半,而在快排中这取决于切分的位置

1.jpg
    public void sort(Comparable[] a) {
        //StdRandom.shuffle(a);
        shuffle(a);    //将数组随机打乱,这一步很重要,会影响性能
        sort(a, 0, a.length - 1);
    }

    public void sort(Comparable[] a, int lo, int hi) {
        if (hi <= lo)
            return;
        int j = partition(a, lo, hi);
        sort(a, lo, j - 1);
        sort(a, j + 1, hi);
    }

    private int partition(Comparable[] a, int lo, int hi) {
        int i = lo, j = hi + 1;
        Comparable v = a[lo];
        while (true) {
            while (less(a[++i], v))
                if (i == hi) break;

            while (less(v, a[--j]))
                if (j == lo) break;

            if (i >= j) break;

            exch(a, i, j);
        }
        exch(a, lo, j);

        return j;
    }

    private boolean less(Comparable v, Comparable w) {
        return v.compareTo(w) < 0;
    }

    private void exch(Object[] a, int i, int j) {
        Object swap = a[i];
        a[i] = a[j];
        a[j] = swap;
    }
    
    private void shuffle(Object[] a) {
        if (a == null) throw new IllegalArgumentException("argument array is null");
        int n = a.length;
        for (int i = 0; i < n; i++) {
            int randomNum = i + uniform(n-i);
            Object temp = a[randomNum];
            a[randomNum] = a[i];
            a[i] = temp;
        }
    }
    
    //[0,n)
    private int uniform(int n) {
        if (n <= 0) throw new IllegalArgumentException("argument must be positive");
        return new Random(System.currentTimeMillis()).nextInt(n);
    }

来看看快速排序的切分轨迹,大小16的数组:

2.jpg
快速排序最理想的情况就是切分正好将数组等分,复杂度为nlgn。最坏情况是一边数组为空,复杂度为N^2/2,我们将数组在开始时打乱就是为了预防这种情况

算法改进

  1. 对于小数组,快速排序比插入排序慢,所以确定一个阀值M,推荐在5~15之间。将if (hi <= lo) return;改为if(hi <= lo + M) {InsertionSort(a, lo, hi); return;}
  2. 对于有大量重复元素的数组,将数组三分,指针lt,gt,i:规定[lo, lt-1]小于切分元素v,[lt, i-1]等于v,[i, gt]为未确定元素,[gt+1, hi]大于v;该方法对于包含大量重复元素的数组,能将排序时间从线性对数级降低到线性级别。
    public void sort(Comparable[] a) {
        shuffle(a);
        sort(a,0,a.length-1);
        assert isSorted(a);
    }
    
    private void sort(Comparable[] a, int lo, int hi) {
        if (hi <= lo) return;
        int lt = lo, gt = hi;
        Comparable v = a[lo];
        int i = lo;
        while (i <= gt) {
            int cmp = a[i].compareTo(v);
            if (cmp < 0)        exch(a, lt++, i++);
            else if (cmp > 0)   exch(a, i, gt--);
            else                i++;
        }
        sort(a, lo, lt-1);
        sort(a, gt+1, hi);
        assert isSorted(a, lo, hi);
    }

相关文章

  • 七大排序算法之快速排序

    七大排序算法之快速排序 @(算法笔记)[排序算法, 快速排序, C++实现] [TOC] 快速排序的介绍: 快速排...

  • 面试准备--排序

    堆排序 快速排序(simple) 快速排序(regular) 归并排序 Shell排序 插入排序 选择排序 冒泡排序

  • 排序

    插入排序 选择排序 冒泡排序 归并排序 快速排序* 三路快速排序

  • 算法笔记01-排序#2

    快速排序敢叫快速排序,那它一定得快。 快速排序 概述 快速排序也是分治排序的典型,它快,而且是原地排序。不过,要防...

  • PHP 实现快速排序

    导语 这篇了解下快速排序。 快速排序 快速排序(英语:Quicksort),又称划分交换排序(partition-...

  • 快速排序的Python实现

    目录 快速排序的介绍 快速排序的Python实现 快速排序的介绍 快速排序(quick sort)的采用了分治的策...

  • 数据结构与算法 快速排序

    起因:快速排序,又称分区交换排序,简称快排,之前没有了解过,抽空学习一下。 快速排序 1 快速排序 快速排序的定义...

  • 数组-快速排序

    采用快速方式对数组进行排序 快速排序百科:快速排序(Quicksort)是对冒泡排序算法的一种改进.快速排序是通过...

  • OC数据结构&算法

    更多整理资料尽在?一平米小站 目录 选择排序 冒泡排序 插入排序 快速排序 双路快速排序 三路快速排序 堆排序 选...

  • 要成功就做一百题-94

    题目名称 今天来几个排序,都是经典题目,包括带拆分的快速排序,堆排序,归并排序。 描述 快速排序快速排序核心就是分...

网友评论

    本文标题:快速排序

    本文链接:https://www.haomeiwen.com/subject/pzqvrxtx.html