Trie (prefix tree) 實現 (Java)

來源:互聯網
上載者:User

 轉載 http://blog.csdn.net/beiyetengqing/article/details/7856113

關注Trie 這種結構已經很久,Trie有一個很有趣的用途,那就是自動提示。而且,前不久在一次面試裡,也需要用Trie來解答。所以,在此對這個資料結構進行總結。

Trie,又稱單詞尋找樹或鍵樹,是一種樹形結構。典型應用是用於統計和排序大量的字串(但不僅限於字串),所以經常被搜尋引擎系統用於文本詞頻統計。它的優點是:最大限度地減少無謂的字串比較,查詢效率比雜湊表高。

它有3個基本性質:

  1. 根節點不包含字元,除根節點外每一個節點都只包含一個字元。
  2. 從根節點到某一節點,路徑上經過的字元串連起來,為該節點對應的字串。
  3. 每個節點的所有子節點包含的字元都不相同。
下面這個圖就是Trie的表示,每一條邊表示一個字元,如果結束,就用星號表示。在這個Trie結構裡,我們有下面字串,比如do, dork, dorm等,但是Trie裡沒有ba, 也沒有sen,因為在a, 和n結尾,沒有結束符號(星號)。


有了這樣一種資料結構,我們可以用它來儲存一個字典,要查詢改字典裡是否有相應的詞,是否非常的方便呢?我們也可以做智能提示,我們把使用者已經搜尋的詞存在Trie裡,每當使用者輸入一個詞的時候,我們可以自動提示,比如當使用者輸入 ba, 我們會自動提示 bat 和 baii.

現在來討論Trie的實現。

首先,我們定義一個Abstract Trie,Trie 裡存放的是一個Node。這個類裡有兩個操作,一個是插入,另一個是查詢。具體實現放在後面。

Node 類的實現

[java] view plaincopy
  1. class Node {  
  2.     char content; // the character in the node  
  3.     boolean isEnd; // whether the end of the words  
  4.     int count;  // the number of words sharing this character  
  5.     LinkedList<Node> childList; // the child list  
  6.     
  7.     public Node(char c){  
  8.         childList = new LinkedList<Node>();  
  9.         isEnd = false;  
  10.         content = c;  
  11.         count = 0;  
  12.     }  
  13.     
  14.     public Node subNode(char c){  
  15.         if(childList != null){  
  16.             for(Node eachChild : childList){  
  17.                 if(eachChild.content == c){  
  18.                      return eachChild;  
  19.                 }  
  20.             }  
  21.         }  
  22.         return null;  
  23.    }  
  24. }  


現在我們來看這個Trie類的具體實現。

[java] view plaincopy
  1. public class Trie{  
  2.     private Node root;  
  3.    
  4.     public Trie(){  
  5.         root = new Node(' ');   
  6.     }  
  7.    
  8.     public void insert(String word){  
  9.         if(search(word) == true) return;  
  10.           
  11.         Node current = root;   
  12.         for(int i = 0; i < word.length(); i++){  
  13.             Node child = current.subNode(word.charAt(i));  
  14.             if(child != null){   
  15.                 current = child;  
  16.             } else {  
  17.                  current.childList.add(new Node(word.charAt(i)));  
  18.                  current = current.subNode(word.charAt(i));  
  19.             }  
  20.             current.count++;  
  21.         }   
  22.         // Set isEnd to indicate end of the word  
  23.         current.isEnd = true;  
  24.     }  
  25.     public boolean search(String word){  
  26.         Node current = root;  
  27.           
  28.         for(int i = 0; i < word.length(); i++){      
  29.             if(current.subNode(word.charAt(i)) == null)  
  30.                 return false;  
  31.             else  
  32.                 current = current.subNode(word.charAt(i));  
  33.         }  
  34.         /*  
  35.         * This means that a string exists, but make sure its 
  36.         * a word by checking its 'isEnd' flag 
  37.         */  
  38.         if (current.isEnd == true) return true;  
  39.         else return false;  
  40.     }  
  41.       
  42.     public void deleteWord(String word){  
  43.         if(search(word) == false) return;  
  44.       
  45.         Node current = root;  
  46.         for(char c : word.toCharArray()) {   
  47.             Node child = current.subNode(c);  
  48.             if(child.count == 1) {  
  49.                 current.childList.remove(child);  
  50.                 return;  
  51.             } else {  
  52.                 child.count--;  
  53.                 current = child;  
  54.             }  
  55.         }  
  56.         current.isEnd = false;  
  57.     }  
  58.       
  59.     public static void main(String[] args) {  
  60.         Trie trie = new Trie();  
  61.         trie.insert("ball");  
  62.         trie.insert("balls");  
  63.         trie.insert("sense");  
  64.       
  65.         // testing deletion  
  66.         System.out.println(trie.search("balls"));  
  67.         System.out.println(trie.search("ba"));  
  68.         trie.deleteWord("balls");  
  69.         System.out.println(trie.search("balls"));  
  70.         System.out.println(trie.search("ball"));  
  71.     }  
  72. }  

時間複雜度分析:

對於insert, 如果被插入的String長度是 k, 每對一個字元進行查詢,我們最多在child linkedlist裡面查詢26次(最多26個字母),所以,複雜度為O(26*k) = O(k). 對於 search, 複雜度是一樣的。

本文代碼來自:http://www.technicalypto.com/2010/04/trie-in-java.html

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.