Java快速排序的實(shí)現(xiàn)詳細(xì)代碼及通俗解釋
快速排序的基本概念:
快速排序的核心就是選擇一個(gè)基準(zhǔn)值,然后將數(shù)組分成兩部分:
- 左邊:比基準(zhǔn)值小的元素。
- 右邊:比基準(zhǔn)值大的元素。 然后遞歸地對(duì)左右兩部分繼續(xù)進(jìn)行這個(gè)過(guò)程,直到每部分都排好序。
來(lái),我們用現(xiàn)實(shí)生活中的例子來(lái)理解!
假設(shè)你在整理一堆數(shù)字卡片??,你想把這些卡片按從小到大的順序排列??焖倥判蚓拖袷悄阏驹谧雷优赃?,對(duì)這些卡片進(jìn)行一次大分揀??,然后不斷地把小卡片和大卡片分成左右兩邊,直到它們都排好位置。
舉個(gè)具體的例子:
你有這樣一堆數(shù)字:
[8, 3, 5, 1, 9, 6]
第一步:選一個(gè)基準(zhǔn)值(pivot)
我們從中間選一個(gè)數(shù)字作為基準(zhǔn)值,比如選擇 6 作為基準(zhǔn)。
第二步:分揀
- 比6小的數(shù)字放到左邊,即:[3, 5, 1]
- 比6大的數(shù)字放到右邊,即:[8, 9]
- 基準(zhǔn)值6就放在中間。
現(xiàn)在我們有了這樣的分揀結(jié)果: 左邊:[3, 5, 1], 中間:6, 右邊:[8, 9]
第三步:遞歸處理左邊和右邊
對(duì)左邊的數(shù)組 [3, 5, 1] 再次進(jìn)行快速排序:
- 選擇基準(zhǔn)值:3
- 左邊:[1] (比3?。?/li>
- 右邊:[5] (比3大)
現(xiàn)在左邊排好了:[1, 3, 5]
右邊的數(shù)組 [8, 9]:
- 這個(gè)部分已經(jīng)排好了,因?yàn)?比9小。
第四步:組合結(jié)果
現(xiàn)在我們把所有部分組合起來(lái):
- 左邊:[1, 3, 5]
- 基準(zhǔn)值:6
- 右邊:[8, 9]
最終得到的排序結(jié)果就是:
[1, 3, 5, 6, 8, 9]
簡(jiǎn)單總結(jié)快速排序的步驟:
- 選擇基準(zhǔn)值:選一個(gè)數(shù)字作為基準(zhǔn)值,通常選擇數(shù)組中的某個(gè)元素。
- 分揀:把比基準(zhǔn)值小的放左邊,比基準(zhǔn)值大的放右邊。
- 遞歸:對(duì)左邊和右邊的部分繼續(xù)進(jìn)行相同的操作。
- 組合結(jié)果:最終把排好序的部分拼在一起。
用生活中的例子來(lái)理解:
Imagine 你要整理一個(gè)大抽屜里的襪子??。你先挑出一只作為“基準(zhǔn)襪”,比如中等長(zhǎng)度的,然后開(kāi)始整理:
- 比基準(zhǔn)襪短的放一邊(左邊)。
- 比基準(zhǔn)襪長(zhǎng)的放另一邊(右邊)。
接著你再分別整理兩邊的襪子,按照同樣的方式繼續(xù)分揀,直到所有的襪子都按長(zhǎng)短排好順序!
快速排序的優(yōu)勢(shì)
快速排序的效率很高,因?yàn)樗看味紝?wèn)題規(guī)模減半。通過(guò)把問(wèn)題分解成小問(wèn)題,它能快速解決排序問(wèn)題。平均時(shí)間復(fù)雜度是 O(n log n),在大多數(shù)情況下比冒泡排序(時(shí)間復(fù)雜度 O(n²))要快得多。
快速排序的完整Java代碼:
public class QuickSortExample {
// 快速排序的主方法,傳入數(shù)組、最小索引和最大索引
public static void quickSort(int[] arr, int low, int high) {
// 如果低索引小于高索引,說(shuō)明數(shù)組還沒(méi)排序完
if (low < high) {
// 找到基準(zhǔn)元素的位置,并把數(shù)組分成兩部分
int pivotIndex = partition(arr, low, high);
// 遞歸地對(duì)基準(zhǔn)左邊部分進(jìn)行快速排序
quickSort(arr, low, pivotIndex - 1);
// 遞歸地對(duì)基準(zhǔn)右邊部分進(jìn)行快速排序
quickSort(arr, pivotIndex + 1, high);
}
}
// 分區(qū)方法:選擇一個(gè)基準(zhǔn)值,把小于基準(zhǔn)的元素放在左邊,大于基準(zhǔn)的放在右邊
private static int partition(int[] arr, int low, int high) {
// 選擇最右邊的元素作為基準(zhǔn)
int pivot = arr[high];
// i是用來(lái)追蹤小于基準(zhǔn)值的元素的位置
int i = low - 1;
// 遍歷數(shù)組,找到所有小于基準(zhǔn)值的元素
for (int j = low; j < high; j++) {
// 如果當(dāng)前元素小于或等于基準(zhǔn)值
if (arr[j] <= pivot) {
i++; // 增加i,準(zhǔn)備交換小元素的位置
// 交換arr[i]和arr[j],把小元素放到前面
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
// 最后,把基準(zhǔn)值放到正確的位置(中間)
int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
// 返回基準(zhǔn)值的正確位置
return i + 1;
}
// 測(cè)試快速排序方法的主函數(shù)
public static void main(String[] args) {
// 定義一個(gè)需要排序的數(shù)組
int[] arr = {8, 3, 5, 1, 9, 6};
// 打印排序前的數(shù)組
System.out.println("排序前的數(shù)組:");
printArray(arr);
// 調(diào)用快速排序方法,排序整個(gè)數(shù)組
quickSort(arr, 0, arr.length - 1);
// 打印排序后的數(shù)組
System.out.println("排序后的數(shù)組:");
printArray(arr);
}
// 輔助方法:打印數(shù)組中的所有元素
private static void printArray(int[] arr) {
for (int num : arr) {
System.out.print(num + " ");
}
System.out.println();
}
}
代碼詳解:
quickSort方法:這是快速排序的主方法。它接收一個(gè)數(shù)組、最小索引(low)和最大索引(high)。如果當(dāng)前子數(shù)組的大小大于1(low < high),它會(huì)找到基準(zhǔn)值的正確位置,然后遞歸地排序左右兩部分。partition方法:這個(gè)方法的作用是將數(shù)組分成兩部分:- 左邊是比基準(zhǔn)值小或相等的元素。
- 右邊是比基準(zhǔn)值大的元素。
它返回的是基準(zhǔn)值最終所在的位置,這樣我們知道從哪里把數(shù)組一分為二。
printArray方法:這個(gè)方法是一個(gè)輔助方法,用來(lái)打印數(shù)組內(nèi)容,方便我們查看排序前后的效果。
解釋這個(gè)例子的通俗版本:
- 選基準(zhǔn)值:
比如我們從數(shù)組[8, 3, 5, 1, 9, 6]中選了6作為基準(zhǔn)值。這個(gè)基準(zhǔn)值就像是一條“分界線”,我們要把小于6的元素放到左邊,把大于6的元素放到右邊。 - 分左右:
遍歷數(shù)組,依次將小于6的元素放在數(shù)組的前面,大于6的元素放到數(shù)組的后面。比如3,5, 和1會(huì)被移到前面,8,9會(huì)放到后面,6作為基準(zhǔn)值就在中間。 - 遞歸處理:
然后我們對(duì)左邊部分[3, 5, 1]和右邊部分[8, 9]繼續(xù)做相同的分揀,直到每個(gè)部分都只有一個(gè)元素為止。 - 排序完成:
最后,所有的元素就按照從小到大的順序排好了,結(jié)果是[1, 3, 5, 6, 8, 9]。
排序前的數(shù)組:
8 3 5 1 9 6
排序后的數(shù)組:
1 3 5 6 8 9
小結(jié):
- 快速排序通過(guò)挑選一個(gè)基準(zhǔn)值,然后將數(shù)組分為兩部分:左邊比基準(zhǔn)小,右邊比基準(zhǔn)大。
- 然后對(duì)左右兩部分繼續(xù)遞歸進(jìn)行快速排序,直到數(shù)組排序完畢。
- 整個(gè)過(guò)程其實(shí)就是不停地“分揀”元素,類似于你把大小不同的物品進(jìn)行快速分揀,最后得到排序結(jié)果。
總結(jié)
到此這篇關(guān)于Java快速排序?qū)崿F(xiàn)的文章就介紹到這了,更多相關(guān)Java快速排序?qū)崿F(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java?GenericObjectPool?對(duì)象池化技術(shù)之SpringBoot?sftp?連接池工具類詳解
這篇文章主要介紹了Java?GenericObjectPool?對(duì)象池化技術(shù)之SpringBoot?sftp?連接池工具類詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04
mybatis-plus生成mapper擴(kuò)展文件的方法
這篇文章主要介紹了mybatis-plus生成mapper擴(kuò)展文件的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Spring Boot Mysql 數(shù)據(jù)庫(kù)操作示例
本篇文章主要介紹了Spring Boot Mysql 數(shù)據(jù)庫(kù)操作示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02
SpringBoot中使用websocket出現(xiàn)404的解決方法
在Springboot中使用websocket時(shí),本地開(kāi)發(fā)環(huán)境可以正常運(yùn)行,但部署到服務(wù)器環(huán)境出現(xiàn)404問(wèn)題,所以本文小編講給大家詳細(xì)介紹一下SpringBoot中使用websocket出現(xiàn)404的解決方法,需要的朋友可以參考下2023-09-09
關(guān)于ArrayList初始化容量的問(wèn)題
這篇文章主要介紹了關(guān)于ArrayList初始化容量的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
淺談springMVC接收前端json數(shù)據(jù)的總結(jié)
下面小編就為大家分享一篇淺談springMVC接收前端json數(shù)據(jù)的總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
Spring?Boot?Security認(rèn)證之Redis緩存用戶信息詳解
本文介紹了如何使用Spring Boot Security進(jìn)行認(rèn)證,并通過(guò)Redis緩存用戶信息以提高系統(tǒng)性能,通過(guò)配置RedisUserDetailsManager,我們成功地將用戶信息存儲(chǔ)到了Redis中,并在Spring Security中進(jìn)行了集成,需要的朋友可以參考下2024-01-01

