java 快速排序算法

来源:互联网 发布:手机号批量加微信软件 编辑:程序博客网 时间:2024/06/13 13:42

快速排序的思想:冒泡+二分+递归分治,冒泡,二分和递归大家应该已经知道了!可以百度一下再回头看本文!
快速排序在实际应用当中也是表现最好的排序算法。快速排序虽然高端,但其实其思想是来自冒泡排序,冒泡排序是通过相邻元素的比较和交换把最小的冒泡到最顶端,而快速排序是比较和交换小数和大数,这样一来不仅把小数冒泡到上面同时也把大数沉到下面。

栗子:对5,3,8,6,4这个无序序列进行快速排序,思路是右指针找比基准数小的,左指针找比基准数大的,交换之。

5,3,8,6,4 用5作为比较的基准,最终会把5小的移动到5的左边,比5大的移动到5的右边。

5,3,8,6,4 首先设置i,j两个指针分别指向两端,j指针先扫描(思考一下为什么?)4比5小停止。然后i扫描,8比5大停止。交换i,j位置。

5,3,4,6,8 然后j指针再扫描,这时j扫描4时两指针相遇。停止。然后交换4和基准数。

4,3,5,6,8 一次划分后达到了左边比5小,右边比5大的目的。之后对左右子序列递归排序(下一次递归得到 左边比4小,右边比4大的排序……),以此类推,最终得到有序序列。

上面留下来了一个问题为什么一定要j指针先动呢?首先这也不是绝对的,这取决于基准数的位置,因为在最后两个指针相遇的时候,要交换基准数到相遇的位置。一般选取第一个数作为基准数,那么就是在左边,所以最后相遇的数要和基准数交换,那么相遇的数一定要比基准数小。所以j指针先移动才能先找到比基准数小的数。

/** *@Description:<p>实现快速排序算法</p> *@author lingang1991 */public static void sort(int[] arr) {        if(arr == null || arr.length == 0)            return ;        //调用快速排序算法        quickSort(arr, 0, arr.length-1);    } public static void quickSort(int[] arr, int left, int right) {        if(left >= right)            return ;        //调用一次划分        int pivotPos = partition(arr, left, right);        //取一次划分后,基数左边的序列进行快速排序(递归本方法,直到left >= right)        quickSort(arr, left, pivotPos-1);        //取一次划分后,基数右边的序列进行快速排序(递归本方法,直到left >= right)        quickSort(arr, pivotPos+1, right);    }public class QuickSort {    //一次划分    public static int partition(int[] arr, int left, int right) {        int pivotKey = arr[left];//基数        int pivotPointer = left;//基数的索引        //从基数的索引开始,设置该索引左指针,设置乱序的最后右指针在末尾        while(left < right) {             //用右指针寻找小于基数的数的索引             while(left < right && arr[right] >= pivotKey)                right --;             //用左指针寻找小于基数的数的索引            while(left < right && arr[left] <= pivotKey)                left ++;            swap(arr, left, right); //把大的交换到右边,把小的交换到左边。        }        swap(arr, pivotPointer, left); //最后把基数交换到中间,基数左边的比基数小,右边的比基数大        return left;    }    public static void swap(int[] arr, int left, int right) {        int temp = arr[left];        arr[left] = arr[right];        arr[right] = temp;    }} 其实上面的代码还可以再优化,上面代码中基准数已经在pivotKey中保存了,所以不需要每次交换都设置一个temp变量,在交换左右指针的时候只需要先后覆盖就可以了。这样既能减少空间的使用还能降低赋值运算的次数。优化代码如下: /** *@Description:<p>实现快速排序算法</p> *@author lingang1991 */public class QuickSort {    /**     * 划分     * @param arr     * @param left     * @param right     * @return     */ public static void sort(int[] arr) {        if(arr == null || arr.length == 0)            return ;        quickSort(arr, 0, arr.length-1);    }   public static void quickSort(int[] arr, int left, int right) {        if(left >= right)            return ;        int pivotPos = partition(arr, left, right);        quickSort(arr, left, pivotPos-1);//对基数前的递归调用        quickSort(arr, pivotPos+1, right);    }    public static int partition(int[] arr, int left, int right) {        int pivotKey = arr[left];        while(left < right) {            while(left < right && arr[right] >= pivotKey)                right --;            arr[left] = arr[right]; //把小的移动到左边            while(left < right && arr[left] <= pivotKey)                left ++;            arr[right] = arr[left]; //把大的移动到右边        }        arr[left] = pivotKey; //最后把pivot赋值到中间        return left;    }}
1 0