平均情况复杂度为nLog2(n)的排序算法

来源:互联网 发布:淘宝怎么采集商品 编辑:程序博客网 时间:2024/05/16 03:12

     平均情况复杂度为nLog2(n)的排序算法

快速排序算法:

什么是快速排序:


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


快速排序基本思想:


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


伪代码:


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指向了轴值记录所在位置,返回该位置。


一次划分:


代码实现:

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))

总结:


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



堆排序算法:


归并排序算法:



0 0
原创粉丝点击