极简算法_快速排序

177 阅读3分钟

简介

快速排序 Qucik Sort 又称为划分交换排序。快速排序是对冒泡排序的一种改进方法。

在冒泡排序中,进行记录关键字的比较和交换是在相邻记录之间进行,记录每次交换只能上移或下移动一个相邻的位置,因而移动和交换的次数比较多。

为什么叫做快速排序?因为在快速排序当中,记录关键字的比较和记录的交换是从两端向中间进行的,待排序关键字较大的记录一次就能交换到后面的单元中,而关键字较小的记录一次就能交换到前面去,由于记录每次移动的距离较远,因此比较和交换的次数减少,所以叫做快速排序

基本思想

首先在无序区 R[low...hign] 中选取一个记录作为排序为基准(可设为 x),用此基准将当前的无序区划分为两个较小的无序区 R[low..i-1]R[i+1...high],并使左边的无序区中所有记录的关键字均小于等于基准关键字,右边的无序区大于所有的记录的关键字均大于基准关键字。而基准关键字 x 则位于最终排序的 x 上。即 R[low...i-1] 中关键字 <= x.key <= R[i+1..high] 中的关键字。

这个过程称为一趟快速排序,当 R[low..i-1]R[i+1..high] 均为非空时,分别对它们进行上述划分,直到所有的无序区中的记录均已排好序为止。

特点

快速排序有以下特点:

  1. 快速排序属于交换排序
  2. 快速排序来说,一般同等值的数字每次排序的结果位置都可能不一样,所以它是不稳定的排序算法
  3. 快速排序结果来说,快速排序有着非常好的时间复杂度,它优于其他各种排序算法。对 n 个记录进行排序的平均时间复杂度为 O(nlog2^n)
  4. 如果待排序的文件的记录已按关键字有序或基本有序时,反而复杂度增大。当复杂度大得离谱的时候,会由快速排序转变为冒泡排序
  5. 根据第四点,一般来可以进行优化。从时间上看,快速排序优于其他算法;从空间来看,快速排序是递归实现的,而递归是需要栈空间来实现递归。而栈的大小取决于递归调用的深度。若一趟排序都能使待排序文件比较均匀地分割成两个子区间,则栈的最大深度为 [log2^n] + 1,即使在最坏的情况下,栈的最大深度也不会超过 n。因此,快速排序需要附加额外的空间为 O(log2^n)

实现

public class QuickSort {

    public int partion(int[] target, int i, int j) {
        //选取一个地方作为对比点
        int ii = target[i];
        
        // 一次循环,包括了 右边检索 和 左边检索
        while (i<j) {
            //先从右边开始检索
            while (i<j&&target[j] >= ii) {
                j--;
            }

            if (i<j) {
                target[i] = target[j];
                i++;
            }

            //然后从左边开始检索
            while (i<j&& target[i] <= ii) {
                target[j] = target[i];
                i++;
            }

            if (i<j) {
                target[j] = target[i];
                j--;
            }
            target[i] = ii;
            return i;
        }

        return 0;
    }

    public void quickSort(int[] target, int low, int high) {
        int p ;
        if (low<high) {
            p = partion(target, low, high);
            quickSort(target, low, p-1);
            quickSort(target, p+1, high);
        }
    }
}

测试

public Test {
    public static void main(String[] args) {
        int[] target = {3,14,55,14,12};
        // 循环输出排序前
        for (int i=0; i < target.length; i++){
            System.out.println(target[i]);
        }
        new QuickSort().quickSort(target, 0, target.length-1);
        //循环输出排序后
        for (int i=0; i < target.length; i++){
            System.out.println(target[i]);
        }
    }
}

完结