【数据结构和算法之排序】快速排序

1.快速排序过程

第一步:选基准元素temp(默认选待排数组第一个值)

第二步:从最高位开始向左依次遍历,j--,直到遇到第j个元素a[j]<temp,那么交换a[j]和a[0]或者将temp直接赋值给a[j];

第三步:从a[i](此时i=0)处向右依次遍历,i++,直到遇到第i个元素a[i]>temp,那么交换temp和a[i]或者将temp值直接赋给a[i];【PS:此时赋值前的temp所在位置并不在数组的第一位置,而是在上次和高位a[j]交换的位置】

第四步:第二步和第三步在大循环中执行完后可以找到temp元素的中间轴所在的位置。循环结束时,i==j,我们接下来需要在[0,i-1]和[i+1,a.lenth-1]区间递归调用quickSort(int[] a,int low,int high)方法。

这里写图片描述

2.快排时间和空间复杂度

快排的最好时间复杂度为O(nlogn),平均时间复杂度为O(nlogn),最坏的情况等于冒泡排序,所以为O(n2)。空间复杂度为O(nlogn),不稳定

3.快速排序递归实现

public class QuickSort {
    /**
     *  递归调用快排方法,分治思想
     * @param numbers 带排序数组
     * @param low  开始位置
     * @param high 结束位置
     */
    public static void quickSort(int[] numbers,int low,int high)
    {
        if(low < high)
        {
            int middle = getMiddle(numbers,low,high); //将numbers数组进行一分为二
            quickSort(numbers, low, middle-1);   //对低字段表进行递归排序
            quickSort(numbers, middle+1, high); //对高字段表进行递归排序
        }
    }
    /**
     * 查找出中轴(默认是最低位low)的在numbers数组排序后所在位置
     * @param numbers 带查找数组
     * @param low   开始位置
     * @param high  结束位置
     * @return  中轴所在位置
     */
    public static int getMiddle(int[] numbers, int low,int high)
    {
        int temp = numbers[low]; //数组的第一个作为中轴
        while(low < high)
        {
            while(low < high && numbers[high] > temp)
            {
                high--;
            }
            numbers[low] = numbers[high];//比中轴小的记录移到低端
            while(low < high && numbers[low] < temp)
            {
                low++;
            }
            numbers[high] = numbers[low] ; //比中轴大的记录移到高端
        }
        numbers[low] = temp ; //中轴记录到尾
        return low ; // 返回中轴的位置
    }

4.快速排序非递归实现【利用栈保存中轴位置】

public class kuaipaifeidigui {
    /**
     * 递归调用快排方法,分治思想
     *
     * @param numbers 带排序数组
     * @param low     开始位置
     * @param high    结束位置
     */
    public static void quickSort(int[] numbers, int low, int high) {
        //存放开始与结束索引
        Stack<Integer> s = new Stack<Integer>();
        //压栈
        s.push(0);
        s.push(numbers.length - 1);
        //利用循环里实现
        while (!s.empty()) {
            high = s.pop();
            low = s.pop();
            //如果最大索引小于等于左边索引,说明结束了
            if (high <= low) continue;

            int i = getMiddle(numbers, low, high);
            if (low < i - 1) {
                s.push(low);
                s.push(i - 1);
            }
            if (i + 1 < high) {
                s.push(i + 1);
                s.push(high);
            }
        }
    }

    /**
     * 查找出中轴(默认是最低位low)的在numbers数组排序后所在位置
     *
     * @param numbers 带查找数组
     * @param low     开始位置
     * @param high    结束位置
     * @return 中轴所在位置
     */
    public static int getMiddle(int[] numbers, int low, int high) {
        int temp = numbers[low]; //数组的第一个作为中轴
        while (low < high) {
            while (low < high && numbers[high] > temp) {
                high--;
            }
            numbers[low] = numbers[high];//比中轴小的记录移到低端
            while (low < high && numbers[low] < temp) {
                low++;
            }
            numbers[high] = numbers[low]; //比中轴大的记录移到高端
        }
        numbers[low] = temp; //中轴记录到尾
        return low; // 返回中轴的位置
    }
}

猜你喜欢

转载自blog.csdn.net/shengmingqijiquan/article/details/77980261