計數排序,基數排序,桶排序

目錄

計數排序:

基數排序:

桶排序:

計數排序:

計數排序是一種非比較型整數排序算法,特別適用于一定范圍內的整數排序。它的核心思想是使用一個額外的數組(稱為計數數組)來計算每個值的出現次數,然后根據這些計數信息將所有的數字放到正確的位置上,從而實現排序。

大致流程就是這樣的,我會用圖和代碼的思想給大家講清楚的:

  1. 確定范圍:首先遍歷一遍待排序的數組,找出其中最大值和最小值,從而確定數字的范圍。這是因為計數排序要求輸入數據在一個已知的有限范圍內。

  2. 初始化計數數組:創建一個長度為最大值與最小值之差加一的計數數組,并將所有元素初始化為0。計數數組的索引代表原始數組中的數值,值則表示該數值出現的次數。

  3. 計數:再次遍歷原始數組,對于每個元素,將計數數組中對應索引的值加一,即統計每個元素出現的次數。

  4. 累加計數:對計數數組進行累加操作,使得計數數組中的每個元素變成小于等于其索引值的所有元素的累計總和。這樣,計數數組中的每個位置就表示了在排序后數組中相應數值的起始位置。

  5. 重建數組:最后,從計數數組反向遍歷原始數組,根據計數數組的信息將元素放到排序后數組的正確位置上。當把一個元素放到排序后數組時,相應地減少計數數組中該元素的計數,以保持計數的準確性。

第一步:創建一個數組,并且找到其中的最大值和最小值

第二步: 定義一個count數組(最大值 減去 最小值 加一),用來統計每個數字出現的次數

?第三步:遍歷count數組,然后按照大小順序把依次放回array數組里面去(可以理解成覆蓋了原數組),最后出來的結果就可以按照大小順序看到每一個數字出現的多少次

最后出來的結果就是:[1, 1, 2, 3, 4, 5, 5, 6, 8, 9, 9]

public static int[] countSort(int[] array){int minval = array[0];int maxval = array[0];for(int i = 0;i<array.length;i++){if(array[i] < minval){minval = array[i];}if(array[i] > maxval){maxval = array[i];}}int[] count = new int[maxval-minval+1];for(int i = 0;i<array.length;i++){int val = array[i];count[val-minval]++;}//遍歷計數數組int index = 0;for(int i = 0;i<count.length;i++){while(count[i]>0){array[index] = i+minval;index++;count[i]--;}}return array;}

?

時間復雜度:

  • 計數排序的時間復雜度主要由兩部分組成:統計每個元素出現次數和根據統計結果重構輸出數組。對于n個元素,范圍在0到k之間的整數排序,計數排序的時間復雜度為O(n+k)。其中,n是數組長度,k是數組中最大值與最小值的差加1。在最好的情況下(即k接近n或n),時間復雜度接近線性,但在k遠大于n時,時間復雜度會顯著增長。

空間復雜度:

  • 計數排序需要額外的空間來存儲每個元素的計數,這個空間取決于待排序數組中元素的范圍。具體來說,需要一個大小為k+1的計數數組,其中k是數組中的最大值與最小值之差加1。因此,空間復雜度為O(k)。如果k與n同數量級,那么空間復雜度也是線性的,即O(n)。

穩定性:

  • 計數排序是一種穩定的排序算法。因為它在統計每個元素的頻率之后,按照元素原來的順序(通過第二個循環從最小元素開始逐個累加計數數組并放回原數組)將元素放回原數組,保證了相同元素的相對位置不會改變。

基數排序:

它的核心思想是將待排序的元素根據其每一位的數值進行分配,這個過程通常從最低有效位(LSD)開始,也可以從最高有效位(MSD)開始,然后按位遞進,直到最高位。基數排序利用了分配式排序的策略,也被稱為“桶排序”的一種推廣。


第一步:首先得有一個數組然后才能對數組進行排序,找到數組中的最大值,確定最大值的位數,比如198就是3位數

第二步:新建一個buckets數組,根據個位十位百位...來存放數據

1.按照個位數排序就是這樣的,然后我們按照先進先出的原則拿出來

?

2.此時的buckets數組就是:

?

3.因為最大為2位數,所以我們還得再進行一個十位的比較

4.?按照先進先出的原則拿出來就得到最終結果

private static int getMaxDigits(int[] array){int maxnum = array[0];for(int num : array){if(num > maxnum){maxnum = num;}}return (int)Math.log10(maxnum)+1;
}public static int[] radixSort(int[] array){int maxnum = getMaxDigits(array);int radix = 10;//基數是10 因為是10進制List<Integer>[] buckets = new ArrayList[radix];for(int i = 0;i < radix;i++){buckets[i] = new ArrayList<>();}for(int digit = 1;digit <= maxnum;digit++){//記得每次要把桶清空for (List<Integer> bucket : buckets) {bucket.clear();}for (int num : array) {int index = (num / (int)Math.pow(10,digit-1))%10;buckets[index].add(num);}//從桶中收集元素到數組int index = 0;for(List<Integer> bucket : buckets){for(int num : bucket){array[index] = num;index++;}}}return array;
}

?

時間復雜度:

  • 基數排序的時間復雜度主要取決于數字的位數(d,即最大數的位數)和待排序元素的數量(n)。
  • 最好、平均和最壞情況下,基數排序的時間復雜度都是O(d*(n+k)),其中k是基數(通常是10,因為基數排序常用于十進制數)。這意味著排序的總成本是元素數量乘以位數,加上每一輪分配和收集過程中桶的管理開銷。當d和k相對于n較小或固定時,基數排序非常高效。

空間復雜度:

  • 空間復雜度主要來自于存儲桶(或列表)的需要。基數排序需要額外的空間來存放每個基數下的元素。最壞情況下,每個元素都會進入不同的桶中,因此空間復雜度為O(n+k)。但實際上,由于基數排序是分輪進行的,每輪只需要足夠的空間來存放每個桶中的元素,理想情況下空間復雜度可以近似為O(n)。但是,考慮到實際實現中可能會為每一輪都分配桶空間,總的空間復雜度還是O(n+k)。

穩定性:

  • 基數排序是穩定的排序算法。這意味著相等的元素在排序前后相對位置保持不變。這是因為基數排序是按位進行的,每一趟排序都是獨立的,并且在收集階段按照原順序從桶中取出元素,從而保持了穩定性。

桶排序:

  1. 初始化桶:首先確定桶的數量和每個桶覆蓋的數值范圍。桶的數量和分布取決于待排序數據的特性,通常需要預先知道數據的大致分布情況。

  2. 分配元素到桶:遍歷待排序數組,根據元素的值將它們分配到對應的桶中。分配的依據可以是元素的大小,例如,如果數據范圍是0到100,可以創建10個桶,每個桶負責10個數的范圍。

  3. 桶內排序:對每個非空的桶內部進行排序。可以選擇插入排序、快速排序等算法,具體選擇取決于桶內元素的數量和特性。

  4. 合并桶:將所有桶中的元素按照桶的順序(通常是桶的索引)依次取出,合并到一個數組中,這樣合并后的數組就是有序的。

?

代碼實現:?

public static int[] bucketSort(int[] arr){int max = Integer.MIN_VALUE;int min = Integer.MAX_VALUE;for(int num : arr){max = Math.max(max,num);min = Math.min(min,num);}//初始化桶int bucketnum = (max-min)/arr.length+1;List<Integer>[] buckets = new ArrayList[bucketnum];for (int i = 0; i < bucketnum; i++) {buckets[i] = new ArrayList<>();}//將每個元素放入桶中for (int i = 0; i < arr.length; i++) {int index = (arr[i] - min) * (bucketnum - 1) / (max - min);buckets[index].add(arr[i]);}//對桶里面的每個元素進行排序,這里可以自己實現其他排序算法for (int i = 0; i < buckets.length; i++) {Collections.sort(buckets[i]);}//重新將桶中的每個元素放回到原數組中int index = 0;for (int i = 0; i < buckets.length; i++) {for(int j = 0;j<buckets[i].size();j++){arr[index] = buckets[i].get(j);index++;}}return arr;}

時間復雜度:

  • 最好情況:如果數據均勻分布在各個桶中,且桶內排序所用的算法具有良好的時間復雜度(如插入排序在小數組上接近O(n)),桶排序的整體時間復雜度可以達到O(n + k),其中n是待排序元素的數量,k是桶的數量。
  • 平均情況:同樣,如果數據分布較為均勻,桶排序的時間復雜度也是O(n + k)。
  • 最壞情況:如果所有數據都集中在少數幾個桶中,特別是全部集中在同一個桶里,此時桶排序的時間復雜度退化,需要對這些桶內的元素進行排序,可能會達到O(n^2),這取決于桶內排序算法的時間復雜度。

空間復雜度:

  • 桶排序的空間復雜度主要取決于桶的數量和每個桶可能存儲的元素數量。最壞情況下,如果每個元素都分配到了不同的桶中,空間復雜度為O(n)加上每個桶的額外開銷。通常,空間復雜度為O(n + k),其中k是桶的數量,n是數組的長度。如果桶的數量k與n成正比或者接近n,那么空間復雜度接近O(n)。

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

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

相關文章

C語言中錯誤處理的基本實現

引入頭文件依賴&#xff1a; 標準輸入輸出流&#xff1a;#include <stdio.h>獲取錯誤信息&#xff1a;#include <string.h>&#xff0c;strerror通過這個頭文件獲取文件流&#xff1a;#include <stdlib.h>&#xff0c;fprintf通過這個頭文件獲取錯誤編號&…

hadoop生態圈集群搭建(持續更新240512)

Hadoop生態圈 Linux1.修改ip地址2.重啟network服務3.安裝插件4.關閉防火墻5.創建用戶6.創建目錄7.修改目錄的所屬主和所屬組為lxy8.修改主機名:hadoop102 (注意名字后面不要加空格)9.修改hosts文件10.等插件都裝完后再重啟Linux11.把xshell的登錄用戶換成lxy &#xff08;注意&…

【TC3xx芯片】TC3xx芯片時鐘監控

目錄 前言 正文 1.時鐘監控概念 1.1 時鐘監控原理 1.2時鐘監控配置寄存器

Node.js 的補充適用場景

Node.js 的適用場景相當廣泛&#xff0c;以下再補充一些具體的使用場景&#xff1a; 服務器端應用開發&#xff1a; Node.js特別適合于構建高性能、高并發、低延遲的服務器端程序。它可以用來開發Web服務器、API服務器、實時通訊服務器等。Node.js的高性能和事件驅動的非阻塞I…

day09-常用API異常

1.時間日期類 1.1 Date類&#xff08;應用&#xff09; 計算機中時間原點 1970年1月1日 00:00:00 時間換算單位 1秒 1000毫秒 Date類概述 Date 代表了一個特定的時間&#xff0c;精確到毫秒 Date類構造方法 方法名說明public Date()分配一個 Date對象&#xff0c;并初始化…

【大數據】HDFS

文章目錄 [toc]HDFS 1.0NameNode維護文件系統命名空間存儲元數據解決NameNode單點問題 SecondaryNameNode機架感知數據完整性校驗校驗和數據塊檢測程序DataBlockScanner HDFS寫流程HDFS讀流程HDFS與MapReduce本地模式Block大小 HDFS 2.0NameNode HANameNode FederationHDFS Sna…

使用注解的方式進行配置RabbitMQ

引入依賴&#xff1a; <dependency><groupId>org.springframework.amqp</groupId><artifactId>spring-rabbit-test</artifactId><scope>test</scope></dependency> 配置application.yml server:port: 8082 spring:rabbitmq…

pyqt5報錯:AttributeError: ‘mywindow‘ object has no attribute ‘setCentralWidget‘

第一種解決方法是&#xff1a;AttributeError: ‘mywindow‘ object has no attribute ‘setCentralWidget‘_attributeerror: mywindow object has no attribute-CSDN博客 第二種解決方法是&#xff08;推薦&#xff09;&#xff1a; 直接把這段代碼復制在 ui轉 py文件的后面…

什么是JVM中的程序計數器

在計算機的體系結構中&#xff1a; 程序計數器&#xff08;Program Counter&#xff09;&#xff0c;通常縮寫為 PC&#xff0c;是計算機體系結構中的一個寄存器&#xff0c;用于存儲下一條指令的地址。程序計數器是控制單元的一部分&#xff0c;它的作用是確保程序能夠按正確…

用 Python 和 AkShare 進行個股數據清洗:簡易多功能方法

標題:用 Python 和 AkShare 進行個股數據清洗:簡易多功能方法 簡介: 本文介紹了如何使用 Python 和 AkShare 庫對個股數據進行清洗和處理。個股數據經常需要進行清洗以用于分析、建模或可視化。我們將介紹一些簡單但功能強大的方法,包括數據加載、缺失值處理、重復值檢測和…

心理應用工具包 psychtoolbox 繪制小球走迷宮

psychtoolbox 是 MATLAB 中的一個工具包&#xff0c;對于科研人員設計實驗范式來說是不二之選&#xff0c;因為它可以操作計算機的底層硬件&#xff0c;精度可以達到幀的級別。 文章目錄 一、實驗目的二、psychtoolbox 的下載安裝三、Psychtoolbox 的基本使用四、完整代碼 一、…

不同數據類型的內部秘密----編程內幕(2)

Q&#xff1a; char類型是如何被當成int處理的&#xff1f; A: 我們可以看看char類型變量在何時才會被當做int處理. #include <stdio.h>int main() {char ch;ch a;printf("%c\n", ch);return 0; } 匯編代碼如下&#xff1a; hellomain:0x100000f60 <0&…

修改了環境變量~/.bashrc后 報錯 命令 “dirname” 可在以下位置找到 * /bin/dirname * /usr/bin/dirname

問題如下&#xff1a; 修改了~/.bashrc后加入了環境變量之后報錯&#xff0c;如下所示 (base) jiedell:~/桌面$ source ~/.bashrc 命令 “dirname” 可在以下位置找到 * /bin/dirname * /usr/bin/dirname 由于 /usr/bin:/bin 不在 PATH 環境變量中&#xff0c;故無法找到該…

在Linux上安裝并啟動Redis

目錄 安裝gcc環境 上傳redis文件方法一&#xff1a;sftp 上傳redis文件方法二&#xff1a;wget 啟動redis-server ctrlc關閉redis-server 參考文章&#xff1a;Linux 安裝 Redis 及踩坑 - 敲代碼的阿磊 - 博客園 (cnblogs.com) 準備&#xff1a;打開VMware Workstation&am…

pair對組創建

創建方式1: pair<type,type> p(value1,value2); pair<string, int> p("Tom", 20); cout << "name:" << p.first << "age:" << p.second << endl; 創建方式2: pair<type,type> pmake_pair(v…

mysql權限分類

USAGE --無權限,只有登錄數據庫,只可以使用test或test_*數據庫 ALL --所有權限 select/update/delete/super/slave/reload --指定的權限 with grant option --允許把自己的權限授予其它用戶(此用戶擁有建立賬號的權限) 權限級別&#xff1a; 1、. &#xff0d;&#xff0d;全…

C語法:for循環執行順序

今天下編寫代碼時遇到了如下情況&#xff1a;期望是輸出 i1,j2 i1,j3 i1,j4 i2,j3 int main(void) {int i,j;for(i1;i<3;i){for(j1;j!i&&j<4;j){printf("i%d,j%d\n",i,j);}}return 0; }實際輸出結果&#xff1a; i2,j1 分析上述代碼&#xff1a…

商務分析方法與工具(九):Python的趣味快捷-Pandas處理公司財務數據集思路

Tips&#xff1a;"分享是快樂的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不僅有知識的海洋&#x1f30a;&#xff0c;還有滿滿的正能量加持&#x1f4aa;&#xff0c;快來和我一起分享這份快樂吧&#x1f60a;&#xff01; 喜歡我的博客的話&#xff0c;記得…

LangChain:大模型框架的深度解析與應用探索

在數字化的時代浪潮中&#xff0c;人工智能技術正以前所未有的速度蓬勃發展&#xff0c;而大模型作為其中的翹楚&#xff0c;以生成式對話技術逐漸成為推動行業乃至整個社會進步的核心力量。再往近一點來說&#xff0c;在公司&#xff0c;不少產品都戴上了人工智能的帽子&#…

初識C語言——第十八天

循環while/do while while 語法結構 while(表達式) 循環語句; break:在while循環中&#xff0c;break用于永久的終止循環 continue:在while循環中&#xff0c;continue的作用是跳過本次循環continue后面的代碼 直接去判斷部分&#xff0c;看是否進行下一次循環。 注意事項…