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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

problem a: 简单的整数排序_什么是基数排序?

發布時間:2025/3/15 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 problem a: 简单的整数排序_什么是基数排序? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

老讀者可能比較熟悉,剛開始的時候寫了一個排序算法系列,把常見的排序算法都寫了,有興趣的可以在公眾號內的目錄菜單欄中選擇數據結構與算法查看。

但是還是有少數的排序算法沒寫,下面的一篇就是。這篇文章用漫畫的形式講解了基數排序,通俗易懂。

—————? 第二天? —————

————————————

什么是計數排序呢?讓我們舉例說明一下。

給定20個隨機整數的值如下:

9,3,5,4,9,1,2,7,8,1,3,6,5,3,4,0,10,9 ,7,9

如何最快地把這些無序的隨機整數排序?

由于這些整數的范圍是從0到10這11個數,我們可以創建一個長度11的空數組,數組從0到10的下標,對應著待排序的隨機整數值0到10:

接下來遍歷這個無序的隨機數列,每一個整數按照其值對號入座,對應數組下標的元素進行加1操作。

比如第一個整數是9,那么數組下標為9的元素加1:

第二個整數是3,那么數組下標為3的元素加1:

繼續遍歷數列并修改數組......

最終,數列遍歷完畢時,數組的狀態如下:

數組每一個下標位置的值,代表了數列中對應整數出現的次數。

有了這個“統計結果”,排序就很簡單了。直接遍歷數組,輸出數組元素的下標值,元素的值是幾,就輸出幾次:

0,1,1,2,3,3,3,4,4,5,5,6,7,7,8,9,9,9,9,10

顯然,這個輸出的數列已經是有序的了。

這就是計數排序的樸素版本。

為了實現穩定排序(排序后,相等元素原本的先后順序不變),真正的計數排序要稍微復雜一些,感興趣的小伙伴可以讀一讀這篇:

漫畫:什么是計數排序?

計數排序有什么局限呢?讓我們看兩個特殊的需求:

需求A,為一組給定的手機號排序:

18914021920

13223132981

13566632981

13660891039

13361323035

........

........

按照計數排序的思路,我們要根據手機號的取值范圍,創建一個空數組。

可是,11位手機號有多少種組合?恐怕要建立一個大得不可想象的數組,才能裝下所有可能出現的11位手機號!

需求B,為一組英文單詞排序:

banana

apple

orange

peach

cherry

........

........

計數排序適合的場景是對整數做排序,如果遇到英文單詞,就無能為力了。

如何有效處理諸如手機號、英文單詞等復雜元素的排序呢?僅僅靠一次計數排序很難實現。

這時候,我們不妨把排序工作拆分成多個階段,每一個階段只根據一個字符進行計數排序,一共排序k輪(k是元素長度)。

或許這樣的描述有些抽象,我們來舉一個例子。

數組中有若干個字符串元素,每個字符串元素都是由三個英文字母組成:

bda,cfd,qwe,yui,abc,rrr,uee

如何將這些字符串按照字母順序排序呢?

由于每個字符串的長度是3個字符,我們可以把排序工作拆分成3輪:

第一輪:按照最低位字符排序。排序過程使用計數排序,把字母的ascii碼對應到數組下標,第一輪排序結果如下:

第二輪:在第一輪排序結果的基礎上,按照第二位字符排序。

需要注意的是,這里使用的計數排序必須是穩定排序,這樣才能保證第一輪排出的先后順序在第二輪還能繼續保持。

比如在第一輪排序后,元素uue在元素yui之前。那么第二輪排序時,兩者的第二位字符雖然同樣是u,但先后順序萬萬不能變,否則第一輪排序就白做了。

第三輪:在第二輪排序結果的基礎上,按照最高位字符排序。

如此一來,這些字符串的順序就排好了。

像這樣把字符串元素按位拆分,每一位進行一次計數排序的算法,就是基數排序(Radix Sort)

基數排序既可以從高位優先進行排序(Most Significant Digit first,簡稱MSD),也可以從低位優先進行排序(Least Significant Digit first,簡稱LSD)。

剛才我們所舉的例子,就是典型的LSD方式的基數排序。

什么意思呢?比如給定如下幾個單詞:

banana

apple

orange

ape

he

這里最長的單詞有6個字符,其余不足6個字符的單詞在末尾補0即可:

banana

apple0

orange

ape000

he0000

在排序時,我們把字符0當做是比a更小的字符,排序結果如下:

ape000

apple0

banana

he0000

orange

//ascii碼的取值范圍

public static final int ASCII_RANGE = 128;

public static String[] radixSort(String[] array,int maxLength)

{

//排序結果數組,用于存儲每一次按位排序的臨時結果

String[] sortedArray = new String[array.length];

//從個位開始比較,一直比較到最高位

for(int k=maxLength-1;k>=0;k--)

{

//計數排序的過程,分成三步:

//1.創建輔助排序的統計數組,并把待排序的字符對號入座,

????????//這里為了代碼簡潔,直接使用ascii碼范圍作為數組長度

int[] count = new int[ASCII_RANGE];

for(int i=0;i<array.length;i++)

{

int index = getCharIndex(array[i],k);

count[index]++;

}

//2.統計數組做變形,后面的元素等于前面的元素之和

for(int i=1;i<count.length;i++)

{

count[i] = count[i] + count[i-1];

}

//3.倒序遍歷原始數列,從統計數組找到正確位置,輸出到結果數組

for(int i=array.length-1;i>=0;i--) {

int index = getCharIndex(array[i],k);

int sortedIndex = count[index]-1;

sortedArray[sortedIndex] = array[i];

count[index]--;

}

//下一輪排序需要以上一輪的排序結果為基礎,因此把結果復制給array

array = sortedArray.clone();

}

return array;

}

//獲取字符串第k位字符所對應的ascii碼序號

private static int getCharIndex(String str, int k){

//如果字符串長度小于k,直接返回0,相當于給不存在的位置補0

if(str.length() < k+1){

return 0;

}

return str.charAt(k);

}

public static void main(String[] args)

{

String[] array = {"qd","abc", "qwe","hhh","a","cws", "ope"};

System.out.println(Arrays.toString(radixSort(array, 3)));

}

這段代碼基于一個大循環來實現,循環進行k次,k就是數組中最長字符串元素的字符數。

在循環體內,執行的是計數排序的邏輯。這個穩定的計數排序算法不太好理解,在小灰往期的漫畫中有進行詳細講解(漫畫:什么是計數排序?)。

—————END—————

趣談編程

讓天下沒有難懂的技術

覺得不錯,點個在看唄

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的problem a: 简单的整数排序_什么是基数排序?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。