快速排序算法

     快速排序算法

什么是快速排序:


快速排序是对冒泡排序的优化,优化的着眼点是:在冒泡排序中,记录的比较和移动是在相邻的位置进行的,记录每次交换后只能向后移动一个位置,因而总的比较和移动次数比较多。在快速排序中,记录和比较是从两端向中间进行的,关键码较大的记录一次就能从前面移到后面,记录移动距离比较远,从而减少了总的比较移动次数

 

快速排序基本思想:


首先选择一个轴值(比较的基准),将待排序记录划分成独立的两部分,左侧记录的关键码均小于或等于轴值,右侧记录的关键码均大于或等于轴值,然后分别对这两部分重复上述过程,知道整个序列有序为止。

 

伪代码:


1:将i和j分别指向待划分区间的最左侧记录和最右侧的记录位置。

2:重复下述过程,知道i==j

    2.1:右侧扫描,直到记录j的关键码小于轴值记录的关键码。

    2.2:如果存在划分区间,则将r[j]和r[i]交换,并i++。

    2.3:左侧扫描,直到记录i的关键码大于轴值记录的关键码。

    2.4:如果存在划分区间,则将r[i]和r[j]交换,并j--。

3:退出循环,说明i和j指向了轴值记录所在位置,返回该位置。

 

一次划分:

快速排序算法_第1张图片

代码实现:

 

package com.renyou.算法工具包;

public class Util {
    
 
    /**
     * 快速排序
     *
     * @param array
     *            待快速排序数组
     * @param first
     *            待快速排序序列的最左边所在位置
     * @param end
     *            待快速排序序列的最右边所在位置
     */
    public static int[] sort(int[] array, int first, int end) {
        int pivot = 0;// 轴值记录所在位置
        if (first < end) {// 区间长度大于一才会执行一次划分,否则递归结束
            pivot = partition(array, first, end);// 进行一次划分
            sort(array, first, pivot - 1);// 递归地对左序列进行快速排序
            sort(array, pivot + 1, end);// 递归地对右序列进行快速排序
        }
        return array;
    }

    /**
     * 快速排序一次划分算法
     *
     * @param array
     *            待快速排序数组
     * @param first
     *            待快速排序序列的最左边所在位置
     * @param end
     *            待快速排序序列的最右边所在位置
     * @return 每次划分序列轴值最后记录所在位置
     */
    public static int partition(int[] array, int first, int end) {

        while (first < end) {
            while (first < end && array[first] <= array[end]) {// 右侧扫描
                end--;
            }
            if (first < end) {
                swap(array, first, end);
                first++;
            }

            while (first < end && array[first] <= array[end]) {// 左侧扫描
                first++;
            }
            if (first < end) {
                swap(array, end, first);
                end--;
            }
        }
        return first;
    }

    /**
     *
     * @param array
     *            待交换数组
     * @param i
     *            待交换数组的一个索引
     * @param j
     *            待交换数组的另一个索引
     */
    public static void swap(int[] array, int i, int j) {
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

 

复杂度分析:


最好情况:每次划分对一个记录定位后,该记录左侧子序列和右侧子序列长度一样。在具有n个记录的序列中,扫描一遍需要O(n)的时间,那么每次划分后正好把待划分区间分成长度相等的两个子序列。则有:

   T(n)<=2T(n/2)+n

          <=2(2T(n/4)+n/2)+n=4T(n/4)+2n

          <=4(2T(n/8)+n/4)+2n=8T(n/8)+3n

           :

           :

           <=nT(1)+nLog2(n)=O(nLog2(n))

最坏情况:待排序序列正好是正序或者逆序列,每次划分只得到比上次少一个的子序列,另一个子序列为空。1/2n(n-1)=O(n*n)

平均情况:O(nLog2(n))

总结:


快速排序是一种不稳定的排序算法,适用于待排序记录个数很大且原始记录数据随机排列的情况,快速排序的平均性能是所有内排序算法最好的一种。

 

 

你可能感兴趣的:(算法数据结构)