字符串排序

鍵索引排序法

鍵索引排序法主要用來解決分組排序的問題。
例如:
一個(gè)班級(jí)有分為三個(gè)組,每個(gè)組編號(hào)1~3。

姓名 組別
Harry 1
Hermione 2
Draco 1
Diamond 3
Steve 3

需要對(duì)以上學(xué)生按照分組來排序,預(yù)期結(jié)果如下。

Harry Draco Hermione Diamond Steve

這種場景之下可以使用鍵索引排序法來實(shí)現(xiàn)。

int N = a.length
String[] aux = new String[N];
int[] count = new int[R+1];

//對(duì)數(shù)據(jù)做頻率統(tǒng)計(jì),a[i].key()為組數(shù),count是頻率統(tǒng)計(jì)的容器
for(int  i=0;i<N;i++)
  count[a[i].key()+1]++;
//頻率轉(zhuǎn)換為索引
for(int r = 0;r<R;r++)
count[r+1] += count[r]
//元素分類即排序
for(int i=0;i<N;i++)
aux[count[a[i].key]++] = a[i];

該算法的時(shí)間復(fù)雜度是O(N+R),一般情況下N>>R,可以看做是O(N)的復(fù)雜度。頻率轉(zhuǎn)換為索引是理解該算法的關(guān)鍵之處,我們可以這樣來看待這個(gè)問題,假設(shè)有一個(gè)hashmap對(duì)于碰撞的處理是簡單插入到散列后的隊(duì)列之后,key為組別而value是姓名,那么我們讀取原始數(shù)據(jù)并根據(jù)組別插入hashmap,發(fā)生碰撞之后連接到尾部。最后從hashmap中按照組別順序?qū)?shù)據(jù)取出來,這就是一個(gè)索引排序?,F(xiàn)在我們統(tǒng)計(jì)每一個(gè)組別中數(shù)據(jù)的數(shù)量,并為此劃分了空間大小(其實(shí)這變相的指定了每個(gè)組別的存放位置),將同組別的直接插入到相應(yīng)位置,使用數(shù)組下標(biāo)作為一個(gè)“哈希散列值”,更方便并且更有效率,這其實(shí)是整個(gè)算法的核心:頻率轉(zhuǎn)換為索引。

低位優(yōu)先的字符串排序

索引排序的一個(gè)應(yīng)用是低位優(yōu)先的字符串排序。低位優(yōu)先字符串排序針對(duì)的是等長的字符串?dāng)?shù)據(jù)的排序,該算法的思路是將ASCII碼中一共256個(gè)值作為分組的依據(jù),字符串從后向前對(duì)每一位做鍵索引排序。

public class TangLSD {
    public static void sort(String[] a, int W){
        int N = a.length;
        int R = 256;
        String[] aux = new String[N];
       //以下為對(duì)字符串從后向前每一個(gè)字符做索引排序
       for(int i=W-1;i>=0;i--){
           int[] count = new int[R+1];
           for(int j=0;j<N;j++){
               count[a[j].charAt(i)+1] ++;
           }
           //頻率轉(zhuǎn)換為索引
           for(int j=0;j<R;j++){
               count[j+1] += count[j];
           }
          //索引處填入字符串
           for(int j=0;j<N;j++){
               aux[count[a[j].charAt(i)]++]=a[j];
           }
          //沒做一次索引我們會(huì)重新賦值一次
           for(int j=0;j<N;j++){
               a[j] = aux[j];
           }
       }
    }

    public static void main(String[] args){
        String[] strs = new String[]{"aadf","dvcd","wdsf","sacd","hgin"};
        sort(strs,1);
        for (String str:strs) {
            System.out.println(str);
        }
    }
}

結(jié)果如下

aadf dvcd hgin sacd wdsf

理解了鍵索引排序,低位優(yōu)先的字符串排序理解起來就自然而然了。粗略的看時(shí)間復(fù)雜度是O(WR)+O(WN),空間復(fù)雜度為R+N。

高位優(yōu)先字符串排序

高位優(yōu)先的排序方法其實(shí)可以看做“分治法”的一種具體實(shí)現(xiàn),首先用鍵索引排序法對(duì)首字母做排序,按照首字母做劃分,對(duì)于首字母相同的字符串做遞歸排序。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容