欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

快速排序QSort详细解析

程序员文章站 2024-03-25 14:31:10
...

笔者在代码中做好了详细注释

package com.ericwei.lib.QuickSort;

import java.util.Arrays;

public class TestQSort {
    public static void main(String[] args) {
        int[] arr = {5, 4, 6, 1, 9, 7, 3, 2, 8};
        qSort(arr, 0, arr.length - 1);
    }

    /**
     * 快速排序的核心思想就是限定中轴
     * 将比中轴小的值放到中轴左边
     * 比中轴大的值放到中轴右边
     * 一次即二分
     * 不断二分到最底层
     * 时间复杂度nlogn,但由于每次二分无法控制左右平均,所以不稳定
     * 
     * @param arr 需要排序的数据
     * @param low 数据左界
     * @param high 数据右界
     */
    public static void qSort(int arr[], int low, int high) {
        /*
            1. 限定左界
            2. 限定右界
            3. 设置中轴,以当前界内第一个值为中轴
         */
        int l     = low;
        int h     = high;
        int pivot = arr[low];

        //如果左界小于右界(说明当前界内元素并未完成二分)
        while (l < h) {
            //将中轴与右边元素进行比较,如果比中轴大,则放在右边不动
            while (l < h && arr[h] >= pivot) {
                h--;
            }
            /*
            此时出现了在右边却又比中轴小的元素,即这个元素要被换到中轴左边
            这种换法不一定说的是直接将元素插到中轴左边
            因为通过l、h限定了未完成分块数据的界,所以只要保证一个相对的位置即可
            */
            if (l < h) {
                int temp = arr[h];
                arr[h] = arr[l];
                arr[l] = temp;
                //完成交换说明这个l位置已经保证该元素数值比中轴小,即处在正确的分块中了
                //则将左界右移动将界缩小
                l++;
            }
            //将中轴与左边元素进行比较,如果比中轴小,则放在左边不动
            while (l < h && arr[l] <= pivot) {
                l++;
            }
            //此时出现了在左边却又比中轴大的元素,即这个元素要被换到中轴右边
            if (l < h) {
                int temp = arr[h];
                arr[h] = arr[l];
                arr[l] = temp;
                h--;
            }
            /*
            因为数据存在一大一小交替的情况,所以一轮分完之后不能保证完成分块
            所以需要通过左右界来判断是否完成
            未完成的话还需再进行继续的分块工作
            */
        }
        //完成以当前中轴为中心的大小左右分块后
        System.out.println(Arrays.toString(arr));
        System.out.print("l=" + (l + 1) + " h=" + (h + 1) + " pivot=" + pivot + "\n");
        /*
        此时数组是
            “[low,l(pivot)]在左,[h(pivot),high]在右”
        的形式
        */
        if (l > low) {
            //如果l>low,说明此次划分左块尚未完成排序
            //重新限定左右界继续向下传递
            qSort(arr, low, l - 1);
        }
        if (h < high) {
            //如果h<high,说明此次划分右块尚未完成排序
            //重新限定左右界继续向下传递
            qSort(arr, l + 1, high);
        }
    }
}
相关标签: 算法 快排