字符串排序(二)

高位優(yōu)先的字符串排序
要實(shí)現(xiàn)一個(gè)通用的字符串排序算法(字符串的長度不一定相同)悠栓,我們應(yīng)當(dāng)考慮從左向右遍歷所有字符柄瑰。顯然换吧,以a開頭的字符串應(yīng)當(dāng)放在以b開頭的字符串之前。實(shí)現(xiàn)這種思想的一個(gè)很自然的方法就是遞歸算法甲抖,被稱為高位優(yōu)先的字符串排序漆改。首先用鍵索引計(jì)數(shù)法將所有字符串按照首字母排序,然后遞歸的將所有首字母對(duì)應(yīng)的子數(shù)組排序准谚。和快速排序一樣挫剑,高位優(yōu)先的字符串排序會(huì)將數(shù)組切分為能夠獨(dú)立排序的子數(shù)組來完成排序任務(wù),但它的切分會(huì)為每個(gè)首字母得到一個(gè)子數(shù)組柱衔,而不是像快速排序那樣產(chǎn)生固定的兩個(gè)或三個(gè)切分樊破。
在高位優(yōu)先的字符串排序算法中,要特別注意到達(dá)字符串末尾的情況唆铐。在排序中哲戚,合理的做法是將所有的字符都已被檢查過的字符串排在所有的子數(shù)組前面,這樣就不需要遞歸的將該子數(shù)組排序艾岂。我們使用一個(gè)接收兩個(gè)參數(shù)的私有方法toChar()來將字符串中的字符索引轉(zhuǎn)化為數(shù)組索引顺少,當(dāng)指定的位置超過了字符串的末尾時(shí)該方法返回-1。然后將所有的返回值加1王浴,得到一個(gè)非負(fù)的int值并用它作為count的索引脆炎。這種轉(zhuǎn)換意味著字符串中每個(gè)字符都可能產(chǎn)生R+1種不同的值:0表示字符串的結(jié)尾,1表示字符串的第一個(gè)字符氓辣,以此類推秒裕。因?yàn)殒I索引計(jì)數(shù)法本來就需要一個(gè)額外的位置,所以使用代碼int count[] = new int[R+2];創(chuàng)建記錄統(tǒng)計(jì)頻率的數(shù)組钞啸。

public class MSD{
    private static int R = 256;              //基數(shù)
    private static final int M = 15;        //小數(shù)組的切換閾值
    private static String[] aux;              //數(shù)組分類的輔助數(shù)組
    private static int charAt(String s, int d)
    { if(d<s.length()) return s.charAt(d); else return -1; }
    public static void sort{String[] a){
        int N = a.length;
        aux = new String[N];
        sort(a, 0, N-1, 0);
    }
    private static void sort(String[] a, int lo, int hi, int d){
        if( hi <= lo+M)
            Insertion.sort(a, lo, hi, d);  return;
        int[] count = new int[R+2];            //計(jì)算頻率
        for(int i=lo; i<=hi; i++)
            count[charAt(a[i], d) +2]++;
        for(int r = 0; r<R; r++)              
            count[r+1] += count[r];              //將頻率轉(zhuǎn)換為索引
        for(int i = lo; i<=hi; i++){
            aux[count[charAt(a[i],d) +1]++] = a[i];      //數(shù)據(jù)分類
        for( int i=lo; i<=hi; i++){
            a[i] = aux[i-lo];                    //回寫
        for( int r =0; r<R; r++)
            sort(a, lo+count[r], lo+count+count[r+1]-1, d+1);
    }
}

三向字符串快速排序
我們也可以根據(jù)高位優(yōu)先的字符串排序算法改進(jìn)快速排序几蜻,根據(jù)鍵的首字母進(jìn)行三向切分,僅在中間子數(shù)組的下一個(gè)字符(因?yàn)殒I的首字母與切分字符相等)繼續(xù)遞歸排序体斩。
三向字符串快速排序只會(huì)將數(shù)組分為三部分梭稚,因此當(dāng)相應(yīng)的高位優(yōu)先的字符串排序產(chǎn)生的非空切分較多時(shí),它需要移動(dòng)的數(shù)據(jù)量就非常巨大硕勿,因?yàn)樗枰M(jìn)行一系列的三向切分才會(huì)獲得多向切分的效果哨毁。但是枫甲,高位優(yōu)先的字符串排序可能會(huì)產(chǎn)生大量(空)子數(shù)組源武,而三向字符串快速排序的切分總是三個(gè)扼褪。因此三項(xiàng)字符串快速排序能很好地處理等值鍵,有較長公共前綴的鍵和取值范圍較小的鍵和小數(shù)組粱栖。

puprivateblic class Quick3string{
    private static int charAt(String s, int d)
    { if(d<s.length()) return s.charAt(d); else return -1; }
    public static void sort(String[] a)
    { sort(a, 0, a.length - 1, 0); }
    private static void sort(String[] a, int lo, int hi, int d){
        if(hi <= lo) return;
        int lt =lo, gt = hi;
        int v = charAt(a[lo], d);
        int i = lo+1;
        while( i<=gt){
            int t = charAt(a[i], d);
            if(t<v) exch(a,lt++, i++);
            else if(t>v) exch(a, i, gt--);
            else  i++;
        }
        sort(a, lo, lt-1, d);
        if( v >= 0) sort(a, lt, gt, d+1);
        sort(a, gt+1, hi, d);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末话浇,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子闹究,更是在濱河造成了極大的恐慌幔崖,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渣淤,死亡現(xiàn)場離奇詭異赏寇,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)价认,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門嗅定,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人用踩,你說我怎么就攤上這事渠退。” “怎么了脐彩?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵碎乃,是天一觀的道長。 經(jīng)常有香客問我惠奸,道長梅誓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任佛南,我火速辦了婚禮证九,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘共虑。我一直安慰自己愧怜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布妈拌。 她就那樣靜靜地躺著拥坛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪尘分。 梳的紋絲不亂的頭發(fā)上猜惋,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音培愁,去河邊找鬼著摔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛定续,可吹牛的內(nèi)容都是我干的谍咆。 我是一名探鬼主播禾锤,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼摹察!你這毒婦竟也來了恩掷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤供嚎,失蹤者是張志新(化名)和其女友劉穎黄娘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體克滴,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡逼争,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了劝赔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氮凝。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖望忆,靈堂內(nèi)的尸體忽然破棺而出罩阵,到底是詐尸還是另有隱情,我是刑警寧澤启摄,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布稿壁,位于F島的核電站,受9級(jí)特大地震影響歉备,放射性物質(zhì)發(fā)生泄漏傅是。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一蕾羊、第九天 我趴在偏房一處隱蔽的房頂上張望喧笔。 院中可真熱鬧,春花似錦龟再、人聲如沸书闸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽浆劲。三九已至,卻和暖如春哀澈,著一層夾襖步出監(jiān)牢的瞬間牌借,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來泰國打工割按, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留膨报,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像现柠,于是被迫代替她去往敵國和親院领。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容