【算法】計數排序、桶排序、基數排序

算法系列八:非比較排序

一、計數排序

1.實現

1.1步驟

1.2代碼

2.性質

2.1穩定性

2.1.1從前往后前始版:

2.1.2從后往前末始版:

2.2復雜度

2.2.1時間復雜度

2.2.2空間復雜度

二、桶排序

1.實現

1.1步驟

1.2代碼

2.穩定性

三、基數排序

1.原理

2.代碼


鴿巢原理

鴿子歸巢,待排序數據歸到有序組群中按大小歸進有序組群來排數越大,歸到的有序組就在越后的數越小,歸到的有序組就在越前的

  • 如果有序組以一個元素一個元素劃分的,實現的是元素組歸巢排序,即計數排序
  • 如果有序組按范圍多個元素為一組劃分的,實現的是范圍組歸巢排序,即桶排序

一、計數排序

1.實現

1.1步驟

  1. 開辟數據范圍內的所有元素都有各自對應的元素組巢穴,范圍內一共有多少種個數據,就開辟每種個數據都有對應的多大的數組,比如90(max) - 10(min) = 80(種個數據)
  2. 歸巢時,通過該數據-數據范圍內的最小值得到所歸巢的下標,然后在數組元素巢中計數表示歸巢
  3. 因為巢內只有一種個數據直接就是有序的,所以所有數據歸完巢在巢層面有序時所有數據就已經有序了,最后將它們按順序地趕出巢加回去即得原來有序的數據


1.2代碼

    public static void countSort(int[] array) {//1.求當前數據的最大值和最小值int minVal = array[0];int maxVal = array[0];for (int i = 1; i < array.length; i++) {if(array[i] < minVal) {minVal = array[i];}if(array[i] > maxVal) {maxVal = array[i];}}//2.根據數據最大值和最小值來確定元素組巢穴數組的大小int[] count = new int[maxVal-minVal+1];//3.遍歷原來的數據進行歸巢排序for (int i = 0; i < array.length; i++) {count[array[i]-minVal]++;}//4.將元素組巢穴里已排好序的數據按順序寫回arrayint index = 0;//重新表示array數組的下標for (int i = 0; i < count.length; i++) {while (count[i] > 0) {array[index] = i+minVal;index++;count[i]--;}}}
}

2.性質

2.1穩定性

每個數據都歸到巢中完成有序時,根據巢中有序來的元素的計數個數,可以將巢改裝成裝每種個元素有序排的始位置,通過對應順序遍歷原數組將數據正確穩定地放在排好序的各自位置上,能實現穩定的排序,所以計數排序是穩定的排序

2.1.1從前往后前始版:

原本巢中裝的是鴿子的計數數量,現在巢里面改裝成裝種個鴿子從前往后的起始位置進行排序:


2.1.2從后往前末始版:

?巢里面改裝成裝種個鴿子從后往前的起始位置進行排序:


2.2復雜度

2.2.1時間復雜度

找最大最小值確定范圍種個數據遍歷原數組用了n原數組數據每個去歸巢用了n范圍x種個元素巢每個去趕,所以時間復雜度為2n + x,即O(n+x)


2.2.2空間復雜度

范圍x種個數據需要開辟x個元素巢的數組,所以空間復雜度為O(x)


二、桶排序

1.實現

1.1步驟

  1. 開辟數據范圍內所有元素都有對應的范圍數組組巢穴將所有數據入范圍組巢穴先進行第一輪巢穴外的排好序,此時巢外已經有序了
  2. 再進行第二輪各自巢穴內的排好序,此時就巢外、巢內都有序所有數據都有序了
  3. 最后按順序地將它們從數組巢中趕出即得有序的數據


1.2代碼

    public static int[] bucketSort(int[] arr) {// 邊界條件:空數組或單個元素直接返回if (arr.length <= 1) {return arr.clone();}// Step 1: 確定數據范圍int minVal = Integer.MAX_VALUE;int maxVal = Integer.MIN_VALUE;for (int num : arr) {if (num < minVal) minVal = num;if (num > maxVal) maxVal = num;}// 處理所有元素相同的情況if (maxVal == minVal) {return arr.clone();}// Step 2: 初始化桶int bucketCount = (int) Math.sqrt(arr.length) + 1; // 桶數量=數組長度的平方根(經驗值)double bucketRange = (double)(maxVal - minVal) / bucketCount;List<List<Integer>> buckets = new ArrayList<>(bucketCount);for (int i = 0; i < bucketCount; i++) {buckets.add(new ArrayList<>());}// Step 3: 元素分配到桶中for (int num : arr) {// 計算元素應該屬于哪個桶int index = (int)((num - minVal) / bucketRange);// 處理最大值剛好落在最后一個桶外的情況if (index == bucketCount) index--;buckets.get(index).add(num);}// Step 4: 對每個桶內部排序for (List<Integer> bucket : buckets) {Collections.sort(bucket); // 使用內置排序算法,決定了桶排序的穩定性}// Step 5: 合并桶int[] sortedArr = new int[arr.length];int idx = 0;for (List<Integer> bucket : buckets) {for (int num : bucket) {sortedArr[idx++] = num;}}return sortedArr;}

2.穩定性

穩定性取決于在第二輪巢內開始排相同大小的元素時所用的排序方法是否具有穩定性


三、基數排序

1.原理

  1. 先進行個位排序,能實現個位一位數有序
  2. 個位有序下,再進行十位優先排序,能實現十位個位兩位數有序
  3. 十個位有序下,再進行百位優先排序,能實現百位十位個位三位數有序


2.代碼

    public static int[] radixSort(int[] arr) {if (arr.length <= 1) {return arr.clone();}// Step 1: 確定最大數的位數int maxNum = Integer.MIN_VALUE;for (int num : arr) {if (num > maxNum) maxNum = num;}// Step 2: 按每位進行計數排序(從低位到高位)int exp = 1; // 從個位開始while (maxNum / exp > 0) {// 初始化10個數字桶(0-9)List<List<Integer>> buckets = new ArrayList<>(10);for (int i = 0; i < 10; i++) {buckets.add(new ArrayList<>());}// 按當前位分配到桶中for (int num : arr) {int digit = (num / exp) % 10; // 提取當前位的數字buckets.get(digit).add(num);}// 重組數組int idx = 0;for (List<Integer> bucket : buckets) {for (int num : bucket) {arr[idx++] = num;}}exp *= 10; // 處理更高位}return arr;}

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

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

相關文章

JDK版本與Spring Boot版本之間對應關系

JDK&#xff08;Java Development Kit&#xff09;版本與Spring Boot版本之間存在一定的對應關系&#xff0c;選擇合適的搭配對項目的穩定性、性能及功能實現至關重要&#xff0c;以下是詳細介紹&#xff1a; 主要版本對應關系 Spring Boot版本發布日期支持的JDK版本備注3.2.…

如何檢測Python項目哪些依賴庫沒有使用

要檢測Python項目中哪些依賴庫未被使用&#xff0c;可以采用以下方法&#xff1a; 1. 使用靜態分析工具 vulture&#xff1a;靜態分析工具&#xff0c;檢測未使用的代碼和導入 pip install vulture vulture your_project/pyflakes&#xff1a;檢查未使用的導入語句 pip ins…

【智能指針】—— 我與C++的不解之緣(三十三)

一、智能指針的使用 還記得&#xff0c;在異常學習的時候&#xff0c;我們分析出了一個問題 double Divide(int x, int y) {if (y 0){throw string("the y is zero");}return (double)x / double(y); } void test(int x, int y) {int* arr new int[10];Divide(x,…

Hadoop+Spark 筆記 2025/4/21

讀書筆記 定義 1. 大數據&#xff08;Big Data&#xff09; - 指傳統數據處理工具難以處理的海量、高速、多樣的數據集合&#xff0c;通常具備3V特性&#xff08;Volume體量大、Velocity速度快、Variety多樣性&#xff09;。擴展后還包括Veracity&#xff08;真實性&#x…

femap許可不足如何解決

在復雜的工程仿真領域&#xff0c;Femap以其強大的功能和廣泛的應用場景而備受青睞。然而&#xff0c;隨著用戶需求的增長和項目規模的擴大&#xff0c;Femap許可不足的問題逐漸凸顯&#xff0c;成為了許多工程師和團隊面臨的挑戰。本文將為您詳細解析Femap許可不足的原因&…

【Microsoft Store 中的軟件推薦】

目錄&#xff1a; &#x1f600; TranslucentTB&#x1f600; Snipaste&#x1f600; Watt Toolkit&#x1f600; NVIDIA Control Panel&#x1f600; Typedown 微軟應用商店中的軟件會直接安裝在C盤&#xff0c;所以&#xff0c;下面分享的這些是即超級好用&#xff0c;又占用…

AOSP Android14 Launcher3——RecentsView最近任務數據加載

最近任務是Launcher中的一個重要的功能&#xff0c;顯示用戶最近使用的應用&#xff0c;并可以快速切換到其中的應用&#xff1b;用戶可以通過底部上滑停頓進入最近任務&#xff0c;也可以在第三方應用底部上滑進最近任務。 這兩種場景之前的博客也介紹過&#xff0c;本文就不…

Flink介紹——實時計算核心論文之Flink論文

引入 通過前面的文章&#xff0c;我們梳理了大數據流計算的核心發展脈絡&#xff1a; S4論文詳解S4論文總結Storm論文詳解Storm論文總結Kafka論文詳解Kafka論文總結MillWheel論文詳解MillWheel論文總結Dataflow論文詳解Dataflow論文總結 而我們專欄的主角Flink正是站在前人的…

極狐GitLab CEO 柳鋼受邀出席 2025 全球機器學習技術大會

極狐GitLab 是 GitLab 在中國的發行版&#xff0c;關于中文參考文檔和資料有&#xff1a; 極狐GitLab 中文文檔極狐GitLab 中文論壇極狐GitLab 官網 2025 年 4 月 18 日至 19 日&#xff0c;2025 全球機器學習技術大會&#xff08;ML-Summit 2025&#xff09;在上海隆重舉行。…

Linux Sed 深度解析:從日志清洗到 K8s 等12個高頻場景

看圖猜詩&#xff0c;你有任何想法都可以在評論區留言哦~ 摘要&#xff1a;Sed&#xff08;Stream Editor&#xff09;作為 Linux 三劍客之一&#xff0c;憑借其流式處理與正則表達式能力&#xff0c;成為運維場景中文本批處理的核心工具。本文聚焦生產環境高頻需求&#xff…

C++ STL 容器簡介(藍橋杯適用精簡版)

C的萬能頭文件是&#xff1a; #include <bits/stdc.h> 一、常用 STL 容器 1.vector&#xff08;動態數組&#xff09; #include<iostream> #include<string> #include <vector> #include <algorithm> // 包含排序所需的頭文件 using namespa…

Java語言的進化:JDK的未來版本

作為一名Java開發者&#xff0c;我們正處在一個令人興奮的時代&#xff01;Java語言正在以前所未有的速度進化&#xff0c;每個新版本都帶來令人驚喜的特性。讓我們一起探索JDK未來版本的發展方向&#xff0c;看看Java將如何繼續領跑編程語言界&#xff01;&#x1f4aa; &…

不要使用Round函數保留小數位了

不要使用Round函數保留小數位了 如果你表格不需要保留公式&#xff0c;那么就不要使用Round函數保留小數位了。用Excel工作圈插件&#xff0c;可以輕松以數值形式保留小數位&#xff0c;且支持合并單元格、不連貫區域快速處理。 如下圖&#xff0c;有文本&#xff0c;有跨行合并…

【C++】入門基礎【下】

目錄 一、缺省參數二、函數重載1. 函數類型不同2. 參數個數不同3、函數類型順序不同 三、引用1、引用的概念和定義2、引用的功能2.1 功能1&#xff1a; 做函數形參&#xff0c;修改形參影響實參2.2 功能2&#xff1a; 做函數形參&#xff0c;減少拷貝&#xff0c;提高效率2.3 功…

git比較不同分支的不同提交文件差異

背景&#xff1a;只想比較某2個分支的某2次提交的差異&#xff0c;不需要帶上父提交。 以commitA為基準&#xff0c;用commitB去比較差異 直接上代碼&#xff1a; commitAxxxx1 commitBxxxx2 outputFile"output.txt"# 獲取與第一個父提交的文件列表 filesA$(git di…

Linux內核之struct pt_regs結構

前沿 項目開發最近進行系統hook功能實現相關業務&#xff0c;主要在centos7和8系列環境開發下關功能。調研了相關知識點&#xff0c;發現在系統7和8上內核版本差別比較大&#xff0c;7-3.10.x系列版本&#xff0c;8-4.18.x系列版本。依據兩個系統的內核情況根對應的內核符號表進…

《從混亂到有序:ArkUI項目文件結構改造指南》

在ArkUI開發的廣袤天地里&#xff0c;構建一個清晰、有序的文件結構&#xff0c;是打造優質應用的關鍵。一個合理的文件結構&#xff0c;就像為開發者精心繪制的地圖&#xff0c;在項目的各個階段&#xff0c;都能提供明確的指引&#xff0c;讓開發過程順暢無阻。今天&#xff…

C#基于Sunnyui框架和MVC模式實現用戶登錄管理

C#基于Sunnyui框架和MVC模式實現用戶登錄管理 1 Controller1.1 UserManagementController.cs&#xff08;控制器入口&#xff09; 2 Model2.1 UserRepository.cs&#xff08;用戶管理模型&#xff09;2.2 User.cs&#xff08;用戶結構體&#xff09;2.3 SQLiteHelper.cs&#x…

自然語言處理(NLP)技術的實例

自然語言處理&#xff08;NLP&#xff09;技術在各個領域都有廣泛的應用&#xff0c;以下是幾個例子&#xff1a; 語音識別&#xff1a;通過NLP技術&#xff0c;計算機可以識別和理解語音指令&#xff0c;例如智能助手如Siri和Alexa就是通過語音識別技術實現與用戶的交互。 機…

Spring Boot實戰(三十六)編寫單元測試

目錄 一、什么是單元測試&#xff1f;二、Spring Boot 中的單元測試依賴三、舉例 Spring Boot 中不同層次的單元測試3.1 Service層3.2 Controller 層3.3 Repository層 四、Spring Boot 中 Mock、Spy 對象的使用4.1 使用Mock對象的背景4.2 什么是Mock對象&#xff0c;有哪些好處…