美文网首页
入门算法:三路快速排序

入门算法:三路快速排序

作者: 半理想主义 | 来源:发表于2020-08-26 17:26 被阅读0次

上手难度:★★★★

算法复杂度:O(nlogn)

排序思想:

预先设定三个空间
l为最左边的索引
初始值lt=l, gt=r+1, i = l + 1
arr[l+1~lt) 存放的是小于v的值
arr[l+1 ~ i)存放的是等于v的值
arr[gt~r]存放的是大于v的值
初始的时候这三个区间都为空
进入while(i < gt)的循环
当arr[i]<v时,将i和lt+1的值交换位置,同时i和lt向右移动,i移动是为了比较下一个值,lt移动是因为左边的区间多了一个值
当arr[i]>v时,将i和gt-1的值交换位置,gt向左移动,i不变,因为交换来的值还未判断,所以i不动
当arr[i]=v时,不做交换操作,i继续向右移动
循环完成后,lt到gt之间的值就不需要再排序了,然后将继续切分小于v的区间和大于v的区间即可

代码实现:

public class QuickSort3 {

    private static Random random = new Random();

    private static int rand(int l, int r){
        return random.nextInt(r - l + 1);
    }

    /**
     * 交换数组中两个元素的位置
     */
    private static void swap(int[] arr, int x, int y){
        if(x < 0 || y < 0 || x > arr.length || y > arr.length){
            return;
        }
        int temp = arr[x];
        arr[x] = arr[y];
        arr[y] = temp;
    }

    /**
     * 对ar[l...r]部分进行快速排序
     */
    public static void quickSort(int[] arr, int l, int r){
        if(l >= r){
            return;
        }

        swap(arr,  l, l + rand(l, r));

        int v = arr[l];

        int lt = l;
        // 索引对应arr[l+1...lt) < v
        int gt = r + 1;
        // 索引对应arr[gt...r] > v
        int i = l + 1;
        // 索引对应arr[lt+1...i) = v 在初始情况下,这些区间都是空的,符合逻辑,首先假设有这样的数组空间了,
        //随着lt、gt、i的变动以及交换位置,就可以把这三个区间确定下来

        //当i移动到从右往左数 最后一个大于v的值的位置时,就不用循环了
        while(i < gt){
            if(arr[i] < v){
                //当i索引的值小于v,就将其与lt+1的值调换位置,同时i继续往右移动,lt因为多了一个值,也要往右移动
                //lt+1的值之前已经判断过了,因此不需要再处理,直接将i移动
                swap(arr, i, lt + 1);
                i++;
                lt++;
            }else if(arr[i] > v){
                //当i索引的值大于v,就将其与gt-1的值调换位置,将大于v的值放到gt区间
                //然后继续判断调换过来的值,因此i不用移动,gt因为多了一个值,所以要往左移动
                swap(arr, i, gt - 1);
                gt--;
            }else{
                i++;
            }
        }
        //l对应的值就是v,lt对应的是最后一个小于v的值,交换后,v就放在了合适的位置,即v的左边小于v,右边大于等于v
        swap(arr, l, lt);

        //注意:这里返回p,之后,只是说满足arr[l+1...j] < v; arr[j+1...i) > v
        //并不是说p的左边一定有数组,或者p的右边一定有数组,也可能是空
        quickSort(arr, l, lt - 1);
        //以p为中间点,再进行快速排序
        quickSort(arr, gt, r);
    }

    public static void main(String[] args) {

        int[] arr = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};

        quickSort(arr, 0, arr.length - 1);

        for( int i = 0 ; i < arr.length ; i ++ ){
            System.out.print(arr[i]);
            System.out.print(' ');
        }

    }
}

优点:

不需要对大量等于v的元素重复操作,在包含大量相同元素时,三路排序最有效率
另外快速排序在 取出数组中第n大的元素这类问题效率很高,算法复杂度为O(n),因为快速排序的过程每一次都是找到一个标定点,然后将标定点挪到数组中合适的位置,这个合适的位置就是数组排好序后最终所处的位置,所以第n大元素,就是第n个位置的元素

相关文章

  • 入门算法:三路快速排序

    上手难度:★★★★ 算法复杂度:O(nlogn) 排序思想: 预先设定三个空间l为最左边的索引初始值lt=l, g...

  • 排序

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

  • 经典排序算法总结

    经典排序算法集锦 冒泡法 排序算法入门之冒泡排序 排序算法入门之冒泡排序优化

  • 算法:排序和搜索

    75 颜色分类快速排序:基于重复元素过多的问题,有双路排序和三路排序算法。双路排序即最常用的写法:参考:https...

  • 算法入门——堆排序

    上篇文章我们学习了算法入门——插入排序、快速排序,这篇文章我们学习算法入门——堆排序。 堆 堆是一种特殊的完全二叉...

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

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

  • OC数据结构&算法

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

  • java实现快速排序、归并排序、希尔排序、基数排序算法...

    快速排序算法 归并排序算法 希尔排序算法 基数排序算法

  • 入门算法:快速排序

    上手难度:★★★☆ 算法复杂度:O(nlogn)~O(n^2) 排序思想: 取最左边索引p对应的值为参考值,循环遍...

  • 快速入门 排序算法

    排序算法 原文:https://github.com/googege/AMAC/tree/master/basic...

网友评论

      本文标题:入门算法:三路快速排序

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