小学生图解排序算法:⑤快速排序

快速排序(Quicksort)是对冒泡排序的一种改进。

快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

                                                              ——来自百度百科

图解算法

图解说明
1. 假定L位标识的元素为a[left],R位标识的元素为a[right],基准值为base。在图解过程中,我们首先将首尾分别标记为a[left]和a[right],并令a[left]为基准值。
2. 从R位向左寻找比base值小的数,即不断重复right–(循环),直到找到合适的值,将此时R位的元素a[right]赋值给此时的L位a[left],即a[left]=a[right]。
3. 从L位向右寻找比base值大的数,即不断重复left++(循环),直到找到合适的值,将此时L位的元素a[left]赋值给此时的R位a[right],即a[right]=a[left]。
4. 不断重复2、3的步骤(循环),不断将小于base的值移到当时的L位,将大于base的值移到当时的R位,直到LR位重合则停止,即循环时left一直是小于right的。
5. 将base的值传给LR重合位,即a[left]=base,或a[right]=base。此时,基准位左侧的数都比基准位小,右侧的数都比基准位大。
6. 将基准位左右侧的数列当成2个独立的数组,分别重复以上步骤排好各自的基准位,此时各自基准位的左侧都是小于基准位的数,右侧都是大于基准位的数。然后将各自基准位左右两侧再次当成2个独立的数组,重复步骤……直到每个独立数组元素只有1个,则该独立数组视为已排序。又因各基准位左侧小,右侧大,所以合并所有单元素独立数组后,源数组即已排好序。(递归)


核心代码

    //用quickSort(a, 0, a.length - 1)调用,a为要排序的数组。
    public static void quickSort(int[] a, int left, int right) {
        if (left < right) {
            int base = a[left];
            int sLeft = left;
            int sRight = right;
            while (sLeft < sRight) {
                while (sLeft < sRight && a[sRight] >= base) {
                    sRight--;
                }
                a[sLeft] = a[sRight];
                while (sLeft < sRight && a[sLeft] <= base) {
                    sLeft++;
                }
                a[sRight] = a[sLeft];
            }
            a[sLeft] = base;

            quickSort(a, left, sLeft - 1);
            quickSort(a, sLeft + 1, right);
        }
    }

优化一下以上代码:

    //用quickSort(a, 0, a.length - 1)调用,a为要排序的数组。
    public static void quickSort(int[] a, int left, int right) {
        //见图解说明,左位要小于右位,当等于时,说明所有位已查找完。
        if (left < right) {
            //每次的基准位下标
            int baseIndex = devision(a, left, right);
            //基准位左侧的数组再细分
            quickSort(a, left, baseIndex - 1);
            //基准位右侧的数组再细分
            quickSort(a, baseIndex + 1, right);
        }
    }

    private static int devision(int[] a, int left, int right) {
        //令首位为基准位,其值为基准值
        int base = a[left];
        while (left < right) {
            //从右向左寻找比base小的数,如有则赋值给L位
            while (left < right && a[right] >= base) {
                right--;
            }
            a[left] = a[right];
            //从左向右寻找比base大的数,如有则赋值给R位
            while (left < right && a[left] <= base) {
                left++;
            }
            a[right] = a[left];
        }
        //寻找完后,将基准值赋值给LR重合位。
        a[left] = base;
        //返回此时的LR重合位作为递归划分左右数组的中心点。
        return left;
    }

注明

基准位没有固定的选值,你可以选择任何一个位置作为基准位。

参考文章

http://www.cnblogs.com/jingmoxukong/p/4302891.html

说明

本文为个人学习笔记,如有细节错误或描述歧义,请留言告知,谢谢!
本文首发于博客专栏: http://Windows9.Win/quick_sort_algorithm

你可能感兴趣的:(算法Algorithm)