算法學習:快速排序

在這里插入圖片描述

🔥 個人主頁:空白詩

在這里插入圖片描述

文章目錄

    • 🚀 引言
    • 📌 快速排序算法核心思想
      • 1. 選擇基準值(Pivot)
      • 2. 分區操作(Partitioning)
      • 3. 遞歸排序子序列
    • 📌 JavaScript 實現
      • 1. 快速排序主函數
      • 2. 分區函數
      • 3. 示例代碼
    • 📌 優化建議
      • 1. 三數取中法
      • 2. 小數組時切換排序算法
      • 3. 尾遞歸優化
      • 4. 并行化處理
    • 📌 時間復雜度分析
    • 📌 總結

🚀 引言

快速排序(Quick Sort)是一種高效的排序算法,由計算機科學界的傳奇人物托尼·霍爾(Tony Hoare)于1960年巧妙地提出。這一算法的核心智慧在于運用了經典的分治法策略——猶如古代兵法中的“分而治之”,將一個錯綜復雜的大列表分割成兩個相對簡單的子列表,隨后對這兩個子列表施以同樣的策略,直到每個子列表都只剩下單一元素或為空,此時整個序列自然歸于有序。此過程宛如構建一座秩序井然的金字塔,自下而上,層層推進。


📌 快速排序算法核心思想

在這里插入圖片描述

1. 選擇基準值(Pivot)

這是算法流程的起點,從數列中精心挑選出一個元素,賦予它一個特殊角色——“基準”(pivot)。基準的選擇可以很靈活,但理想情況下應傾向于選擇一個能將數據集大致均勻分割的值,以促進算法效率。

2. 分區操作(Partitioning)

分區操作是快速排序的精髓所在。其目標是在遍歷數列一次的過程中,通過交換元素位置,使得所有小于基準值的元素都位于基準之前,而所有大于基準值的元素都排列在其后相等的元素可以放置在任一側,完成這一操作后,基準值恰好位于其最終排序后的位置,即序列的中間。這一巧妙劃分不僅為后續遞歸奠定了基礎,也直接體現了快速排序分而治之的哲學。

3. 遞歸排序子序列

基于分區結果,數列被明確劃分為兩個獨立的部分:左側全部小于基準值,右側則大于基準值。接下來,算法會對這兩個子序列遞歸地應用同樣的排序邏輯。通過不斷地將問題規模減半,直到每個子序列只剩下一個或零個元素(這時自然視為已排序),整個數列便會在這一系列遞歸調用中逐步構建出全局的有序狀態。這一策略確保了快速排序高效利用了分治策略的優勢,尤其是在平均情況下展現出極高的效率。


📌 JavaScript 實現

1. 快速排序主函數

function quickSort(arr, left = 0, right = arr.length - 1) {// 如果左指針小于右指針,說明還有未排序的區間if (left < right) {// 調用分區函數,返回pivot的索引,完成一次分區const pivotIndex = partition(arr, left, right);// 對pivot左邊的子數組進行快速排序quickSort(arr, left, pivotIndex - 1);// 對pivot右邊的子數組進行快速排序quickSort(arr, pivotIndex + 1, right);}// 返回排序后的數組,實際上由于是原地排序,此處return并非必要return arr;
}

2. 分區函數

function partition(arr, left, right) {// 選擇最右側元素作為基準值pivotconst pivot = arr[right];let i = left; // i為小于pivot的元素的邊界,初始時指向最左側// 遍歷除了pivot外的所有元素for (let j = left; j < right; j++) {// 如果當前元素小于或等于pivotif (arr[j] <= pivot) {// 交換arr[i]和arr[j],并將i右移一位,保持i左側的元素都小于等于pivot[arr[i], arr[j]] = [arr[j], arr[i]]; // ES6解構賦值進行交換i++; }}// 最后將pivot(arr[right])與arr[i]交換,使得pivot位于正確的位置上[arr[i], arr[right]] = [arr[right], arr[i]];// 返回pivot的最終位置索引return i;
}

3. 示例代碼

// 未排序數組示例
const unsortedArray = [3, 6, 8, 10, 1, 2, 1];// 打印原始數組
console.log("Unsorted:", unsortedArray);// 調用快速排序函數,得到排序后的數組
const sortedArray = quickSort(unsortedArray);// 打印排序后的數組
console.log("Sorted:", sortedArray);

這段代碼實現了快速排序算法,通過quickSort函數遞歸地將數組分為更小的子數組,并通過partition函數完成每部分的排序,最終達到整個數組有序的目的。代碼中使用了ES6的解構賦值來簡化元素交換的操作,使得代碼更加簡潔易讀。


📌 優化建議

1. 三數取中法

  • 核心思想:通過更智能地選擇基準值(pivot)來優化快速排序的性能。
  • 操作步驟
    1. 比較數組首部、中部、尾部的元素。
    2. 選取這三個數中的中位數作為分區操作的基準值。
    3. 這樣做能有效平衡劃分,即使在數據部分有序的情況下也能保持較好的性能,減少最壞情況的發生概率。

2. 小數組時切換排序算法

  • 適用條件:當待排序序列的元素數量較少時(例如少于10或15個)。
  • 策略詳情:快速排序在小數組上的優勢不明顯,此時切換到插入排序等簡單排序算法更為高效。因為插入排序在小數據集上具有較低的常數因子和無需遞歸的優點,能夠快速完成排序,與快速排序形成互補。

3. 尾遞歸優化

  • 概念闡述:確保遞歸調用是函數的最后一個操作,便于某些支持該特性的編譯器進行優化。
  • 實施方法:設計遞歸邏輯時,直接在遞歸調用的返回語句中返回計算結果,避免在遞歸返回后還需執行其他操作。
  • 注意事項:雖然JavaScript等語言不一定能自動優化尾遞歸,遵循此原則編寫代碼依然有助于提高可讀性和未來跨平臺移植的兼容性。

4. 并行化處理

  • 目標:利用多核CPU資源加速排序過程。
  • 實施步驟
    1. 將大數組分割成多個小塊。
    2. 各個CPU核心獨立并行地對分塊數據執行快速排序。
    3. 最后合并各塊已排序的結果。
  • 優勢:在擁有多個處理器核心的系統上,此策略能顯著縮短排序時間,尤其適合處理海量數據。

通過上述一系列優化措施,快速排序算法不僅在理論上保持了較高的時間效率,在實際應用中也變得更加靈活和健壯,能夠有效應對各種規模數據集的排序挑戰,展現出更高的性能和穩定性。


📌 時間復雜度分析

在這里插入圖片描述

在這里插入圖片描述

快速排序算法的性能極大程度上取決于基準值(Pivot)的選擇策略。

  • 最優情況:若每次分區操作都能均勻地將數據集切分為兩部分,每部分包含近似相等數量的元素,則遞歸樹的深度為log?n。鑒于每一層遞歸涉及遍歷數組,總體操作計數約為n * log?n。因此,快速排序在最佳情況下的時間復雜度為O(n log n),表現出高度的效率。

  • 最差情況:相反,若每次選取的基準值都導致極不均衡的分區,極端情形下每次僅將數組分為一個元素和剩余所有元素兩部分,這將導致遞歸深度上升至n,伴隨每次遍歷數組的操作,時間復雜度惡化為O(n2),與冒泡排序相近。

  • 平均情況:在實踐中,若假定分區大致均勻,即每次都能將數據集分為兩個大小相似的子集,快速排序的平均時間復雜度同樣為O(n log n)。這對于多數隨機分布數據集而言,是一個非常高效的排序方案。

鑒于最壞情況下的性能瓶頸,實際部署快速排序算法時,往往配合采用基準值優化策略,比如“三數取中法”,來增強其魯棒性和普遍適用性,確保在多種數據條件下仍能保持高效的排序性能。


📌 總結

快速排序算法通過分治法策略實現高效排序,其核心包括選擇基準值、分區操作及遞歸排序子序列三大步驟。為了進一步提升性能和適應不同場景,可采納諸如三數取中法優化基準選擇、小數組時切換至插入排序、尾遞歸優化及并行處理等策略。這些優化不僅能夠減少最壞情況出現的概率,還充分利用現代計算資源,使快速排序在實踐中表現得更為出色,成為處理大量數據排序任務的優選算法之一。

總之,快速排序憑借其高效與靈活性,在眾多排序算法中占據重要地位,廣泛應用于各種數據排序需求之中。


在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/13889.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/13889.shtml
英文地址,請注明出處:http://en.pswp.cn/web/13889.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于Perfetto 解讀一幀的生產消費流程 Android >= S Qualcomm

廣告 首先幫我朋友打個廣告 我們一起在運營一個視頻號 感興趣的可以幫忙點擊右邊這個小鈴鐺 鈴鐺 序 1.這個流程里面的東西如果展開其實是有很多的 內容其實還是比較淺顯的 sf處就不貼源碼了 關一個Vsync就有的解釋 當然筆者在流程上先形成一個思維閉環 2.如有小伙伴需要 筆…

Java方法的遞歸

Java方法的遞歸 前言一、遞歸的概念示例代碼示例 二、遞歸執行過程分析代碼示例執行過程圖 三、遞歸練習代碼示例按順序打印一個數字的每一位(例如 1234 打印出 1 2 3 4)遞歸求 1 2 3 ... 10寫一個遞歸方法&#xff0c;輸入一個非負整數&#xff0c;返回組成它的數字之和. …

零基礎學Java第二十一天之IIO流之對象流

IO流之對象流 1、對象流 1、理解 將對象寫入到文件&#xff0c;將文件里的對象讀取到程序中 class ObjectInputStream – 對象輸入流 class ObjectOutputStream – 對象輸出流 序列化/鈍化&#xff1a;程序里的對象 寫入到 文件中 反序列化/活化&#xff1a;文件中的對象 讀取…

【OpenCV實戰】OpenCV實現自動調整亮度和對比度

一,基于局部直方圖信息增強算法 對比度受限的自適應直方圖均衡化(Contrast Limited Adaptive Histogram Equalization,簡稱CLAHE)是一種用于圖像增強的技術,其原理主要基于自適應直方圖均衡化(Adaptive Histogram Equalization,簡稱AHE)但增加了對比度限制來避免過度放…

uniapp藍牙打印圖片

前言 這是個藍牙打印圖片的功能&#xff0c;業務是打印界面固定的demo范圍&#xff0c;這里通過html2canvas插件生成的圖片base64&#xff0c;然后圖片base64繪制到canvas中去后&#xff0c;獲取canvas中的像素信息&#xff0c;然后對像素信息進行一個灰度值處理&#xff0c;灰…

在Linux系統中解決Java生成海報文字亂碼和缺少字體文件的問題

在Linux系統中,如果缺少特定的字體文件,可以通過以下幾種方法來解決: 1. 安裝系統字體包 大多數Linux發行版提供了各種字體包,可以通過包管理器安裝這些字體包。例如,在Debian/Ubuntu系統上,可以使用以下命令安裝常見的字體包: # 安裝基本的字體包 sudo apt-get updat…

Java集合的組內平均值怎么計算

要計算Java集合&#xff08;例如List或Set中的Integer、Double或其他數值類型的對象&#xff09;的組內平均值&#xff0c;我們需要遍歷這個集合&#xff0c;累加所有的元素值&#xff0c;然后除以集合的大小&#xff08;即元素的數量&#xff09;。以下是一個詳細的步驟說明和…

opencl色域變換,處理傳遞顯存數據

在使用ffmpeg解碼后的多路解碼數據非常慢&#xff0c;還要給AI做行的加速方式是在顯存處理數據&#xff0c;在視頻拼接融合產品的產品與架構設計中&#xff0c;提出了比較可靠的方式是使用cuda&#xff0c;那么沒有cuda的顯卡如何處理呢 &#xff0c;比較好的方式是使用opencl來…

go語言的一些常見踩坑問題

開始之前&#xff0c;介紹一下?最近很火的開源技術&#xff0c;低代碼。 作為一種軟件開發技術逐漸進入了人們的視角里&#xff0c;它利用自身獨特的優勢占領市場一角——讓使用者可以通過可視化的方式&#xff0c;以更少的編碼&#xff0c;更快速地構建和交付應用軟件&#…

安卓手機APP開發__網絡連接性支持VPN

安卓手機APP開發__網絡連接性支持VPN 安卓提供了API給開發者,來創建一個虛擬的私有網絡(VPN)的解決方案. 根據這里的介紹,你能知道如何開發和測試你的針對安卓設備的VPN的客戶端. 概述 VPN允許設備為了安全地連接網絡,而沒有物理性的連接在一個網絡上. 安卓包括了一個內嵌的…

【無重復字符的最長子串】python,滑動窗口+哈希表

滑動窗口哈希表 哈希表 seen 統計&#xff1a; 指針 j遍歷字符 s&#xff0c;哈希表統計字符 s[j]最后一次出現的索引 。 更新左指針 i &#xff1a; 根據上輪左指針 i 和 seen[s[j]]&#xff0c;每輪更新左邊界 i &#xff0c;保證區間 [i1,j] 內無重復字符且最大。 更新結…

使用JSDOM安全截斷文章HTML內容

在Web開發中&#xff0c;經常需要處理大量的HTML內容&#xff0c;尤其是在展示文章預覽、動態加載內容或限制顯示長度等場景中。直接截斷HTML字符串可能會導致頁面布局混亂、樣式錯誤或標簽不完整等問題。為了安全地截斷HTML內容&#xff0c;我們可以利用jsdom庫來解析HTML&…

JVM學習-垃圾回收器(一)

垃圾回收器 按線程數分類 串行垃圾回收器 串行回收是在同一時間段內只允許有一個CPU用于執行垃圾回收操作&#xff0c;此時工作線程被暫停&#xff0c;直至垃圾收集工作結束 在諸如單CPU處理器或者較小的應用內存等硬件平臺不是特別優越的場合&#xff0c;串行回收器的性能表…

http和https的區別,怎么免費實現https(內涵教學)

超文本傳輸協議HTTP協議被用于在Web瀏覽器和網站服務器之間傳遞信息&#xff0c;HTTP協議以明文方式發送內容&#xff0c;不提供任何方式的數據加密&#xff0c;如果攻擊者截取了Web瀏覽器和網站服務器之間的傳輸報文&#xff0c;就可以直接讀懂其中的信息&#xff0c;因此&…

etcd 和 MongoDB 的混沌(故障注入)測試方法

最近在對一些自建的數據庫 driver/client 基礎庫的健壯性做混沌&#xff08;故障&#xff09;測試, 去驗證了解業務的故障處理機制和恢復時長. 主要涉及到了 MongoDB 和 etcd 這兩個基礎組件. 本文會介紹下相關的測試方法. MongoDB 中的故障測試 MongoDB 是比較世界上熱門的文…

AI網絡爬蟲:批量爬取電視貓上面的《慶余年》分集劇情

電視貓上面有《慶余年》分集劇情&#xff0c;如何批量爬取下來呢&#xff1f; 先找到每集的鏈接地址&#xff0c;都在這個class"epipage clear"的div標簽里面的li標簽下面的a標簽里面&#xff1a; <a href"/drama/Yy0wHDA/episode">1</a> 這個…

速盾:負載均衡能防ddos攻擊嗎?

負載均衡是一種分布式系統的設計思想&#xff0c;通過將流量分散到多個服務器上&#xff0c;以提高系統的穩定性和可擴展性。然而&#xff0c;負載均衡本身并不能完全防止DDoS攻擊&#xff0c;但可以在一定程度上減輕其影響。 DDoS&#xff08;分布式拒絕服務&#xff09;攻擊…

【C語言】8.C語言操作符詳解(1)

文章目錄 1.操作符的分類2.?進制和進制轉換3.原碼、反碼、補碼4.移位操作符4.1 左移操作符4.2 右移操作符 5.位操作符&#xff1a;&、|、^、~5.1 &&#xff1a;按位與5.2 |&#xff1a;按位或5.3 ^&#xff1a;按位異或5.4 ~&#xff1a;按位取反5.5 例題例題1例題2例…

短視頻矩陣系統4年獨立開發正規代發布接口源碼搭建部署開發

1. 短視頻矩陣源碼技術開發要求及實現流程&#xff1a; 短視頻矩陣源碼開發要求具備視頻錄制、編輯、剪輯、分享等基本功能&#xff0c;支持實時濾鏡、特效、音樂等個性化編輯&#xff0c;能夠實現高效的視頻渲染和處理。開發流程主要包括需求分析、技術選型、設計架構、編碼實…

Web前端開發技術、詳細文章、(例子)html 列表、有序列表、無序列表、列表嵌套

目錄 列表概述 列表類型與標記符號 無序列表 語法&#xff1a; 語法說明&#xff1a; 無序列表標記的 type 屬性及其說明 代碼解釋 有序列表 基本語法 屬性說明 1、列表 o1標記的屬性 2、列表項li標記的屬性 有序列表 o1標記的屬性、值 代碼解釋 列表嵌套 基本…