快速排序--單邊循環法


遞歸的精髓在於放棄!放棄你對於理解和跟蹤遞歸全程的企圖,只理解遞歸兩層之間的交接,以及遞歸終結的條件。

快速排序和冒泡排序一樣,也屬於交換排序.和冒泡排序不同的是,快速排序在每一輪選中1個基准元素,並讓其它比它大的元素移動到一邊,比它小的移動到另一邊,從而把數列拆解成兩個部分.這種思路叫作分治法.

 

通過以上描述,快速排序實現分成2步:

1. 獲取基准元素

2. 元素的交換

 

 基准元素的選擇 

毫無疑問,最簡單的方式就是選擇數列的第1個元素作為基准元素.

 

 元素的交換 

元素的交換實現有兩種方式:單邊循環法雙邊循環法.先記錄單邊循環法的思路.

舉個例子,將一下數組,從小到大進行升序排序:

4, 7, 3, 5, 6, 2, 8, 1

一. 首先獲取基准元素standardValue,同時設置一個mark指針指向數列起始位置,mark指針表示小於基准元素的區域邊界.用以上數組來說:

standardValue=4, mark=0 

二. 然后,從基准元素的下一位(即7)開始遍歷數組:

如果遍歷到的元素大於基准元素,繼續遍歷;

如果遍歷到的元素小於基准元素,需要完成:

1.將mark指針右移1位,因為小於基准元素的區域邊界增大了1;

2.將最新遍歷到的元素和mark指針指向的元素進行交換,因為最新遍歷的元素屬於小於基准元素standardValue的區域.

4, 3, 2, 1, 6, 7, 8, 5 

三. 最后,將基准元素和指針指向的元素交換,這一輪宣告結束,將看到的數組是這樣:

1, 3, 2, 4, 6, 7, 8, 5 

實現了將數組中比基准元素4小的元素移動到了左邊, 比基准元素4大的元素移動到了右邊, 分成左右兩個部分, 然后對左右兩個部分繼續一 二 三的步驟,也就是遞歸.

 

 單邊循環法的實現 

package com.xgcd.lab.sort;

import java.util.Arrays;

/**
 * @description: 快速排序
 * @author: liangyadong
 * @date: 2021/6/29 23:24
 */
public class QuickSort {

    public static void quickSort(int[] arr, int startIndex, int endIndex) {
        // 遞歸結束條件
        if (startIndex >= endIndex) {
            return;
        }

        // 1.得到基准元素位置
        int standardIndex = partition(arr, startIndex, endIndex);

        // 2.根據基准元素,分成兩個部分進行遞歸排序
        quickSort(arr, startIndex, standardIndex - 1);
        quickSort(arr, startIndex + 1, endIndex);

    }

    /**
     * 分治(單邊循環法)
     *
     * @param arr        待交換的數組
     * @param startIndex 起始下標
     * @param endIndex   結束下標
     * @return 基准元素的位置
     */
    private static int partition(int[] arr, int startIndex, int endIndex) {
        // 取第一位元素作為基准元素
        int standardValue = arr[startIndex];
        // 指針指向數列的起始位置,mark代表小於基准元素的區域邊界
        int mark = startIndex;

        // 遍歷數組,如果遍歷到的元素小於基准元素: 1. 2.
        for (int i = startIndex + 1; i <= endIndex; i++) {
            if (arr[i] < standardValue) {
                // 1.指針右移一位
                mark++;
                // 2.並將當前遍歷到的元素和指針所指元素交換
                int temp = arr[i];
                arr[i] = arr[mark];
                arr[mark] = temp;
            }
        }

        // 遍歷結束,將基准元素和指針指向的元素交換,這一輪宣告結束
        arr[startIndex] = arr[mark];
        arr[mark] = standardValue;
        return mark;
    }

    public static void main(String[] args) {
        int[] arr = new int[]{4, 7, 3, 5, 6, 2, 8, 1};
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }
}
 

 下集預告 

下篇記錄一下快速排序的雙邊循環法.

 


作者:習慣沉淀,一直在路上的北漂碼畜

 

原文

https://mp.weixin.qq.com/s/YUiTzISHdhCsBxkChXlUwg

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM