日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

排序算法之计数排序、基数排序和桶排序

發(fā)布時間:2025/3/21 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 排序算法之计数排序、基数排序和桶排序 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

轉(zhuǎn)自:http://www.cnblogs.com/ttltry-air/archive/2012/08/04/2623302.html

? ?計數(shù)排序,基數(shù)排序,桶排序等非比較排序算法,平均時間復雜度都是O(n)。這些排序因為其待排序元素本身就含有了定位特征,因而不需要比較就可以確定其前后位置,從而可以突破比較排序算法時間復雜度O(nlgn)的理論下限。

計數(shù)排序(Counting sort)

????計數(shù)排序(Counting sort)是一種穩(wěn)定的排序算法。計數(shù)排序是最簡單的特例,由于用來計數(shù)的數(shù)組C的長度取決于待排序數(shù)組中數(shù)據(jù)的范圍(等于待排序數(shù)組的最大值與最小值的差加上1),這使得計數(shù)排序?qū)τ跀?shù)據(jù)范圍很大的數(shù)組,需要大量時間和內(nèi)存,適用性不高。例如:計數(shù)排序是用來排序0到100之間的數(shù)字的最好的算法,但是它不適合按字母順序排序人名。但是,計數(shù)排序可以用在基數(shù)排序中的算法來排序數(shù)據(jù)范圍很大的數(shù)組。當輸入的元素是?n 個 0 到 k 之間的整數(shù)時,它的運行時間是?Θ(n?+?k)。

??? 假定輸入是個數(shù)組A【1...n】, length【A】=n。 另外還需要一個存放排序結(jié)果的數(shù)組B【1...n】,以及提供臨時存儲區(qū)的C【0...k】(k是所有元素中最大的一個)。算法偽代碼

算法的步驟如下

  • 找出待排序的數(shù)組中最大和最小的元素
  • 統(tǒng)計數(shù)組中每個值為t的元素出現(xiàn)的次數(shù),存入數(shù)組C的第t項
  • 對所有的計數(shù)累加(從C中的第一個元素開始,每一項和前一項相加)
  • 反向填充目標數(shù)組:將每個元素t放在新數(shù)組的第C(t)項,每放一個元素就將C(t)減去1
  • 算法實現(xiàn):

    1: /* 2: * 算法的步驟如下: 3: 1、找出待排序的數(shù)組中最大和最小的元素 4: 2、統(tǒng)計數(shù)組中每個值為t的元素出現(xiàn)的次數(shù),存入數(shù)組C的第t項 5: 3、對所有的計數(shù)累加(從C中的第一個元素開始,每一項和前一項相加) 6: 4、反向填充目標數(shù)組:將每個元素t放在新數(shù)組的第C(t)項,每放一個元素就將C(t)減去1 7: * */ 8: public class CountingSort { 9: // 類似bitmap排序 10: public static void countSort(int[] a, int[] b, final int k) { 11: // k>=n 12: int[] c = new int[k + 1]; 13: for (int i = 0; i < k; i++) { 14: c[i] = 0; 15: } 16: for (int i = 0; i < a.length; i++) { 17: c[a[i]]++; 18: } 19: System.out.println("\n****************"); 20: System.out.println("計數(shù)排序第2步后,臨時數(shù)組C變?yōu)?#xff1a;"); 21: for (int m:c) { 22: System.out.print(m + " "); 23: } 24: 25: for (int i = 1; i <= k; i++) { 26: c[i] += c[i - 1]; 27: } 28: System.out.println("\n計數(shù)排序第3步后,臨時數(shù)組C變?yōu)?#xff1a;"); 29: for (int m:c) { 30: System.out.print(m + " "); 31: } 32: 33: for (int i = a.length - 1; i >= 0; i--) { 34: b[c[a[i]] - 1] = a[i];//C[A[i]]-1 就代表小于等于元素A[i]的元素個數(shù),就是A[i]在B的位置 35: c[a[i]]--; 36: } 37: System.out.println("\n計數(shù)排序第4步后,臨時數(shù)組C變?yōu)?#xff1a;"); 38: for (int n:c) { 39: System.out.print(n + " "); 40: } 41: System.out.println("\n計數(shù)排序第4步后,數(shù)組B變?yōu)?#xff1a;"); 42: for (int t:b) { 43: System.out.print(t + " "); 44: } 45: System.out.println(); 46: System.out.println("****************\n"); 47: } 48:? 49: public static int getMaxNumber(int[] a) { 50: int max = 0; 51: for (int i = 0; i < a.length; i++) { 52: if (max < a[i]) { 53: max = a[i]; 54: } 55: } 56: return max; 57: } 58:? 59: public static void main(String[] args) { 60: int[] a = new int[] { 2, 5, 3, 0, 2, 3, 0, 3 }; 61: int[] b = new int[a.length]; 62: System.out.println("計數(shù)排序前為:"); 63: for (int i = 0; i < a.length; i++) { 64: System.out.print(a[i] + " "); 65: } 66: System.out.println(); 67: countSort(a, b, getMaxNumber(a)); 68: System.out.println("計數(shù)排序后為:"); 69: for (int i = 0; i < a.length; i++) { 70: System.out.print(b[i] + " "); 71: } 72: System.out.println(); 73: } 74:? 75: }

    ?

    基數(shù)排序(radix sorting)

    ??????基數(shù)排序(radix sorting)將所有待比較數(shù)值(正整數(shù))統(tǒng)一為同樣的數(shù)位長度,數(shù)位較短的數(shù)前面補零。 然后 從最低位開始,依次進行一次排序。這樣從最低位排序一直到最高位排序完成以后, 數(shù)列就變成一個有序序列。具體過程可以參考動畫演示。

    ???? 假設我們有一些二元組(a,b),要對它們進行以a為首要關鍵字,b的次要關鍵字的排序。我們可以先把它們先按照首要關鍵字排序,分成首要關鍵字相同的若干堆。然后,在按照次要關鍵值分別對每一堆進行單獨排序。最后再把這些堆串連到一起,使首要關鍵字較小的一堆排在上面。按這種方式的基數(shù)排序稱為MSD(Most Significant Dight)排序。第二種方式是從最低有效關鍵字開始排序,稱為LSD(Least Significant Dight)排序。首先對所有的數(shù)據(jù)按照次要關鍵字排序,然后對所有的數(shù)據(jù)按照首要關鍵字排序。要注意的是,使用的排序算法必須是穩(wěn)定的,否則就會取消前一次排序的結(jié)果。由于不需要分堆對每堆單獨排序,LSD方法往往比MSD簡單而開銷小。下文介紹的方法全部是基于LSD的。

    ????? 基數(shù)排序的簡單描述就是將數(shù)字拆分為個位十位百位,每個位依次排序。因為這對算法穩(wěn)定要求高,所以我們對數(shù)位排序用到上一個排序方法計數(shù)排序。因為基數(shù)排序要經(jīng)過d (數(shù)據(jù)長度)次排序, 每次使用計數(shù)排序, 計數(shù)排序的復雜度為 On),? d 相當于常量和N無關,所以基數(shù)排序也是 O(n)。基數(shù)排序雖然是線性復雜度, 即對n個數(shù)字處理了n次,但是每一次代價都比較高, 而且使用計數(shù)排序的基數(shù)排序不能進行原地排序,需要更多的內(nèi)存, 并且快速排序可能更好地利用硬件的緩存, 所以比較起來,像快速排序這些原地排序算法更可取。對于一個位數(shù)有限的十進制數(shù),我們可以把它看作一個多元組,從高位到低位關鍵字重要程度依次遞減。可以使用基數(shù)排序?qū)σ恍┪粩?shù)有限的十進制數(shù)排序

    ??? 例如我們將一個三位數(shù)分成,個位,十位,百位三部分。我們要對七個三位數(shù)來進行排序,依次對其個位,十位,百位進行排序,如下圖:

    很顯然,每一位的數(shù)的大小都在[0,9]中,對于每一位的排序用計數(shù)排序再適合不過。

    算法實現(xiàn):

    1: // 基數(shù)排序:穩(wěn)定排序 2: public class RadixSorting { 3:? 4: // d為數(shù)據(jù)長度 5: private static void radixSorting(int[] arr, int d) { 6: //arr = countingSort(arr, 0); 7: for (int i = 0; i < d; i++) { 8: arr = countingSort(arr, i); // 依次對各位數(shù)字排序(直接用計數(shù)排序的變體) 9: print(arr,i+1,d); 10: } 11: } 12: 13: // 把每次按位排序的結(jié)果打印出來 14: static void print(int[] arr,int k,int d) 15: { 16: if(k==d) 17: System.out.println("最終排序結(jié)果為:"); 18: else 19: System.out.println("按第"+k+"位排序后,結(jié)果為:"); 20: for (int t : arr) { 21: System.out.print(t + " "); 22: } 23: System.out.println(); 24: } 25: 26: // 利用計數(shù)排序?qū)υ氐拿恳晃贿M行排序 27: private static int[] countingSort(int[] arr, int index) { 28: int k = 9; 29: int[] b = new int[arr.length]; 30: int[] c = new int[k + 1]; //這里比較特殊:數(shù)的每一位最大數(shù)為9 31:? 32: for (int i = 0; i < k; i++) { 33: c[i] = 0; 34: } 35: for (int i = 0; i < arr.length; i++) { 36: int d = getBitData(arr[i], index); 37: c[d]++; 38: } 39: for (int i = 1; i <= k; i++) { 40: c[i] += c[i - 1]; 41: } 42: for (int i = arr.length - 1; i >= 0; i--) { 43: int d = getBitData(arr[i], index); 44: b[c[d] - 1] = arr[i];//C[d]-1 就代表小于等于元素d的元素個數(shù),就是d在B的位置 45: c[d]--; 46: } 47: return b; 48: } 49:? 50: // 獲取data指定位的數(shù) 51: private static int getBitData(int data, int index) { 52: while (data != 0 && index > 0) { 53: data /= 10; 54: index--; 55: } 56: return data % 10; 57: } 58:? 59: public static void main(String[] args) { 60: // TODO Auto-generated method stub 61: int[] arr = new int[] {326,453,608,835,751,435,704,690,88,79,79};//{ 333, 956, 175, 345, 212, 542, 99, 87 }; 62: System.out.println("基數(shù)排序前為:"); 63: for (int t : arr) { 64: System.out.print(t + " "); 65: } 66: System.out.println(); 67: radixSorting(arr, 4); 68: } 69:? 70: }

    ?

    桶排序(Bucket Sort)

    ??? 首先定義桶,桶為一個數(shù)據(jù)容器,每個桶存儲一個區(qū)間內(nèi)的數(shù)。依然有一個待排序的整數(shù)序列A,元素的最小值不小于0,最大值不超過K假設我們有M個桶,第i個桶Bucket[i]存儲i*K/M至(i+1)*K/M之間的數(shù)。桶排序步驟如下:

  • 掃描序列A,根據(jù)每個元素的值所屬的區(qū)間,放入指定的桶中(順序放置)。
  • 對每個桶中的元素進行排序,什么排序算法都可以,例如插入排序。
  • 依次收集每個桶中的元素,順序放置到輸出序列中。
  • ???? 具體過程可以參考動畫演示。

    算法偽代碼為:

    具體代碼:

    ?

    1: // 桶排序 2: public class BucketSort { 3:? 4: // 插入排序 5: static void insertSort(int[] a) { 6: int n = a.length; 7: for (int i = 1; i < n; i++) { 8: int p = a[i]; 9: insert(a, i, p); 10: } 11: } 12:? 13: static void insert(int[] a, int index, int x) { 14: // 元素插入數(shù)組a[0:index-1] 15: int i; 16: for (i = index - 1; i >= 0 && x < a[i]; i--) { 17: a[i + 1] = a[i]; 18: } 19: a[i + 1] = x; 20: } 21:? 22: private static void bucketSort(int[] a) { 23: int M = 10; // 11個桶 24: int n = a.length; 25: int[] bucketA = new int[M]; // 用于存放每個桶中的元素個數(shù) 26: // 構(gòu)造一個二維數(shù)組b,用來存放A中的數(shù)據(jù),這里的B相當于很多桶,B[i][]代表第i個桶 27: int[][] b = new int[M][n]; 28: int i, j; 29: for (i = 0; i < M; i++) 30: for (j = 0; j < n; j++) 31: b[i][j] = 0; 32:? 33: int data, bucket; 34: for (i = 0; i < n; i++) { 35: data = a[i]; 36: bucket = data / 10; 37: b[bucket][bucketA[bucket]] = a[i];// B[0][]中存放A中進行A[i]/10運算后高位為0的數(shù)據(jù),同理B[1][]存放高位為1的數(shù)據(jù) 38: bucketA[bucket]++;// 用來計數(shù)二維數(shù)組中列中數(shù)據(jù)的個數(shù),也就是桶A[i]中存放數(shù)據(jù)的個數(shù) 39: } 40: System.out.println("每個桶內(nèi)元素個數(shù):"); 41: for (i = 0; i < M; i++) { 42: System.out.print(bucketA[i] + " "); 43: } 44: System.out.println(); 45:? 46: System.out.println("數(shù)據(jù)插入桶后,桶內(nèi)未進行排序前的結(jié)果為:"); 47: for (i = 0; i < M; i++) { 48: for (j = 0; j < n; j++) 49: System.out.print(b[i][j] + " "); 50: System.out.println(); 51: } 52:? 53: System.out.println("對每個桶進行插入排序,結(jié)果為:"); 54: // 下面使用直接插入排序?qū)@個二維數(shù)組進行排序,也就是對每個桶進行排序 55: for (i = 0; i < M; i++) { 56: // 下面是對具有數(shù)據(jù)的一列進行直接插入排序,也就是對B[i][]這個桶中的數(shù)據(jù)進行排序 57: if (bucketA[i] != 0) { 58: // 插入排序 59: for (j = 1; j < bucketA[i]; j++) { 60: int p = b[i][j]; 61: int k; 62: for (k = j - 1; k >= 0 && p < b[i][k]; k--) 63: { 64: assert k==-1; 65: b[i][k + 1] = b[i][k]; 66: } 67: b[i][k + 1] = p; 68: } 69: } 70: } 71: 72: // 輸出排序過后的順序 73: for (i = 0; i < 10; i++) { 74: if (bucketA[i] != 0) { 75: for (j = 0; j < bucketA[i]; j++) { 76: System.out.print(b[i][j] + " "); 77: } 78: } 79: } 80: } 81:? 82: /** 83: * @param args 84: */ 85: public static void main(String[] args) { 86: // TODO Auto-generated method stub 87: int[] arr = new int[] {3,5,45,34,2,78,67,34,56,98}; 88: bucketSort(arr); 89: } 90:? 91: }

    三種線性排序的比較

    排序算法 時間復雜度 空間復雜度 ?
    計數(shù)排序 O(N+K) O(N+K) 穩(wěn)定排序
    基數(shù)排序 O(N) O(N) 穩(wěn)定排序
    桶排序 O(N+K) O(N+K) 穩(wěn)定排序

    ???? 從整體上來說,計數(shù)排序,桶排序都是非基于比較的排序算法,而其時間復雜度依賴于數(shù)據(jù)的范圍,桶排序還依賴于空間的開銷和數(shù)據(jù)的分布。而基數(shù)排序是一種對多元組排序的有效方法,具體實現(xiàn)要用到計數(shù)排序或桶排序。

    ???? 相對于快速排序、堆排序等基于比較的排序算法,計數(shù)排序、桶排序和基數(shù)排序限制較多,不如快速排序、堆排序等算法靈活性好。但反過來講,這三種線性排序算法之所以能夠達到線性時間,是因為充分利用了待排序數(shù)據(jù)的特性,如果生硬得使用快速排序、堆排序等算法,就相當于浪費了這些特性,因而達不到更高的效率。


    總結(jié)

    以上是生活随笔為你收集整理的排序算法之计数排序、基数排序和桶排序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: www.18av| 伊人网色| www.youjizz.com中国 | 精品日韩中文字幕 | 韩国视频一区二区 | 一区二区三区激情 | 色婷婷六月天 | 老熟女高潮一区二区三区 | 日本欧美日韩 | 潘金莲一级淫片aaaaa | 免费三片在线观看网站v888 | 少妇专区 | 久久综合久久综合久久 | 日韩激情第一页 | 亚洲国产精品久久久久爰色欲 | 久久91精品国产91久久小草 | 亚洲成av人影院 | 99国产精品白浆在线观看免费 | 午夜激情视频在线 | 日韩一区二区三区在线免费观看 | 日韩欧美一二三 | 中文字幕精品国产 | 97精品人妻一区二区三区在线 | 欧美日韩一本 | 国产免费一级 | 2019国产精品| 欧美xx视频 | 久久xxxx| 日韩欧美综合久久 | 91亚洲精品久久久蜜桃借种 | 美女视频黄免费 | 少妇精品无码一区二区 | 天天躁日日躁狠狠躁伊人 | 日韩亚洲区 | 亚洲精品日日夜夜 | 久久女人| jizz网站| 激情小说五月天 | 色婷婷国产精品 | 香蕉视频在线视频 | 在线观看色视频 | 欧美成人精品欧美一 | 国产sm在线| 国产精品99久久久久久人 | 黄网地址| 色综合天天干 | 蜜桃av影院| 国产日产亚洲精品 | 欧美日韩在线一区 | 国产高清一 | 精品区在线观看 | 精品久久久在线观看 | 18岁禁黄网站 | 天天操天天干天天摸 | 午夜av在线免费观看 | 久久奇米| 国产精品久久久久高潮 | 日本在线视频一区二区三区 | 欧美性天天影院 | 九九九国产 | 能看的av网站 | 激情欧美一区二区三区精品 | 成人免费在线电影 | 337p日本欧洲亚洲大胆精筑 | 秋霞视频在线观看 | 精品日韩一区二区三区四区 | 男女av| 天堂影院一区二区 | 夜夜躁狠狠躁日日躁av | 古装做爰无遮挡三级聊斋艳谭 | 成人午夜一区二区 | 亚洲成人福利 | 国产精品zjzjzj在线观看 | 黄色中文视频 | 日本少妇吞精囗交视频 | 综合久久亚洲 | 97热久久 | 成人aaa| 欧美日韩极品 | 国产精品亚洲无码 | 人人射人人干 | 激情视频一区二区 | 91亚洲精品在线观看 | 香港一级淫片免费放 | 办公室摸腿吻胸激情视频 | 一区二区日韩电影 | 91日韩在线视频 | 熟女视频一区二区三区 | 国产成人在线视频网站 | 欧美成人短视频 | 国产精品熟女久久久久久 | 免费观看视频一区 | www.香蕉.com | 麻豆视频免费版 | av噜噜色| 日韩免费观看一区二区 | 毛片在线网 | 欧洲成人在线视频 | 久热这里只有精品6 |