數(shù)據(jù)結(jié)構(gòu)之字典樹

Trie樹了袁,即字典樹朗恳、前綴樹,又稱單詞查找樹或鍵樹载绿,是一種樹形結(jié)構(gòu)粥诫,是一種哈希樹的變種。典型應(yīng)用是用于統(tǒng)計和排序大量的字符串(但不僅限于字符串)崭庸,所以經(jīng)常被搜索引擎系統(tǒng)用于文本詞頻統(tǒng)計怀浆。它的優(yōu)點是:最大限度地減少無謂的字符串比較。
總的來說怕享,Trie的思想是以空間換空間执赡,利用字符串的公共前綴來降低查找操作帶來的時間開銷以達到提高效率的目的。
主要性質(zhì)

  1. 根節(jié)點不包含字符函筋,除根節(jié)點之外每一個節(jié)點都只包含有且一個字符沙合;
  2. 從根節(jié)點到某一節(jié)點,路徑上經(jīng)過的字符連接起來跌帐,為該節(jié)點對應(yīng)的字符串首懈;
  3. 每個節(jié)點的所有子節(jié)點包含的字符都不相同;

一.字典樹的定義

  public class Trie{
    Trie[] root;              //孩子節(jié)點谨敛,代表下一個字符
    boolean isPause;   //是否終止 
    public Trie(){
      root = new Trie[26];
      isPause = false;
    }
  }

二.字典樹的創(chuàng)建

void insert(String word)向前綴樹中插入字符串 word 究履。
栗子:好比假設(shè)有b,abc脸狸,abd最仑,bcd,abcd肥惭,efg盯仪,hii 這6個單詞,那我們創(chuàng)建trie樹就得到:

img

所以我們可以得到以下代碼:

    /** Inserts a word into the trie. */
    public void insert(String word) {
        int length = word.length();
        Trie cur = this;
        for(int i = 0; i < length; i++){
            int index =word.charAt(i) - 'a';  //這里獲得第i個字符的所在位置
            if(cur.children[index] == null){//如果該分支不存在,那么創(chuàng)建
                cur.children[index] = new Trie();
            }
            cur = cur.children[index]; //令cur指向當前單詞蜜葱,準備執(zhí)行下一次操作
        }
       //單詞插入完成后全景,需要將其此單詞末尾字符的標記位 置true,代表此字符是單詞的結(jié)尾
        cur.isPause = true;  
    }

三.字符串的查找

    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        int length = word.length();
        Trie cur = this;
        for(int i = 0; i < length; i++){
            int index = word.charAt(i) - 'a';
            //如果下一個字符匹配不上,直接返回牵囤。
            if(cur.children[index] == null){
                return false;
            }else{
                cur = cur.children[index];
            }
        }
        //遍歷所有待查詢單詞的字符爸黄,返回待查詢末尾字符是否為一個單詞的結(jié)尾字符。
        return cur.isPause;
    }

四.字符串前綴的查找

boolean startsWith(String prefix) 如果之前已經(jīng)插入的字符串 word 的前綴之一為 prefix 揭鳞,返回 true 炕贵;否則,返回 false 野崇。

    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        int length = prefix.length();
        Trie cur = this;
        for(int i = 0; i < length; i++){
            int index = prefix.charAt(i) - 'a';
          //如果下一個字符匹配不上称开,直接返回。
            if(cur.children[index] == null){
                return false;
            }else{
                cur = cur.children[index];
            }
        }  
        //這里和字符串查詢的區(qū)別在于, 只要滿足一個單詞的前綴就返回true
        return true;
    }

五.代碼匯總

class Trie {
    Trie[] children;
    boolean isPause;
    /** Initialize your data structure here. */
    public Trie() {
        children = new Trie[26]; 
        isPause = false;
    }
    
    /** Inserts a word into the trie. */
    public void insert(String word) {
        int length = word.length();
        Trie cur = this;
        for(int i = 0; i < length; i++){
            int index =word.charAt(i) - 'a';
            if(cur.children[index] == null){
                cur.children[index] = new Trie();
            }
            cur = cur.children[index];
        }
        cur.isPause = true;
    }
    
    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        int length = word.length();
        Trie cur = this;
        for(int i = 0; i < length; i++){
            int index = word.charAt(i) - 'a';
            if(cur.children[index] == null){
                return false;
            }else{
                cur = cur.children[index];
            }
        }
        return cur.isPause;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        int length = prefix.length();
        Trie cur = this;
        for(int i = 0; i < length; i++){
            int index = prefix.charAt(i) - 'a';
            if(cur.children[index] == null){
                return false;
            }else{
                cur = cur.children[index];
            }
        }
        return true;

    }
}

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * boolean param_2 = obj.search(word);
 * boolean param_3 = obj.startsWith(prefix);
 */

總結(jié)

時間復(fù)雜度:初始化為 O(1)鳖轰,其余操作為 O(|S|)清酥,其中 |S| 是每次插入或查詢的字符串的長度。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蕴侣,一起剝皮案震驚了整個濱河市焰轻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌昆雀,老刑警劉巖辱志,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異狞膘,居然都是意外死亡揩懒,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門客冈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來旭从,“玉大人稳强,你說我怎么就攤上這事场仲。” “怎么了退疫?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵渠缕,是天一觀的道長。 經(jīng)常有香客問我褒繁,道長亦鳞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任棒坏,我火速辦了婚禮燕差,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘坝冕。我一直安慰自己徒探,他們只是感情好,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布喂窟。 她就那樣靜靜地躺著测暗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪磨澡。 梳的紋絲不亂的頭發(fā)上碗啄,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機與錄音稳摄,去河邊找鬼稚字。 笑死,一個胖子當著我的面吹牛厦酬,可吹牛的內(nèi)容都是我干的胆描。 我是一名探鬼主播褒傅,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼袄友!你這毒婦竟也來了殿托?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤剧蚣,失蹤者是張志新(化名)和其女友劉穎支竹,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸠按,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡礼搁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了目尖。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片馒吴。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖瑟曲,靈堂內(nèi)的尸體忽然破棺而出饮戳,到底是詐尸還是另有隱情,我是刑警寧澤洞拨,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布扯罐,位于F島的核電站,受9級特大地震影響烦衣,放射性物質(zhì)發(fā)生泄漏歹河。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一花吟、第九天 我趴在偏房一處隱蔽的房頂上張望秸歧。 院中可真熱鬧,春花似錦衅澈、人聲如沸键菱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纱耻。三九已至,卻和暖如春险耀,著一層夾襖步出監(jiān)牢的瞬間弄喘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工甩牺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蘑志,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像急但,于是被迫代替她去往敵國和親澎媒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

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