<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Change Dir

    先知cd——熱愛生活是一切藝術(shù)的開始

    統(tǒng)計(jì)

    留言簿(18)

    積分與排名

    “牛”們的博客

    各個(gè)公司技術(shù)

    我的鏈接

    淘寶技術(shù)

    閱讀排行榜

    評(píng)論排行榜

    最簡(jiǎn)Trie的實(shí)現(xiàn)

    無(wú)附加功能,主要提供insert,search和prefixsearch。具體原理請(qǐng)參見http://en.wikipedia.org/wiki/Trie

    先來(lái)看下trie樹的樣子:

    圖片來(lái)源wikipedia

       1: public class Node {
       2:     char content;
       3:     boolean marker;
       4:     Collection<Node> child;
       5:     boolean visited;
       6:  
       7:     public Node(char c) {
       8:         child = new LinkedList<Node>();
       9:         marker = false;
      10:         content = c;
      11:         visited = false;
      12:     }
      13:  
      14:     public Node subNode(char c) {
      15:         if (child != null) {
      16:             for (Node eachChild : child) {
      17:                 if (eachChild.content == c) {
      18:                     return eachChild;
      19:                 }
      20:             }
      21:         }
      22:         return null;
      23:     }
      24: }

    Node是一個(gè)trie樹的節(jié)點(diǎn),其中content表示節(jié)點(diǎn)對(duì)應(yīng)的字符,marker表示是否該節(jié)點(diǎn)是否是一個(gè)單詞的完結(jié)節(jié)點(diǎn)。child顧名思義是節(jié)點(diǎn)的所有子節(jié)點(diǎn)集合,visited在遍歷時(shí)需要,表示是否訪問過(guò)。

    具體trie:

       1: public class Trie {
       2:     private Node root;
       3:  
       4:     public Trie() {
       5:         root = new Node(' ');
       6:     }
       7:  
       8:     public void insert(String s) {
       9:         Node current = root;
      10:         if (s.length() == 0) // For an empty character
      11:             current.marker = true;
      12:         for (int i = 0; i < s.length(); i++) {
      13:             Node child = current.subNode(s.charAt(i));
      14:             if (child != null) {
      15:                 current = child;
      16:             } else {
      17:                 current.child.add(new Node(s.charAt(i)));
      18:                 current = current.subNode(s.charAt(i));
      19:             }
      20:             // Set marker to indicate end of the word
      21:             if (i == s.length() - 1)
      22:                 current.marker = true;
      23:         }
      24:     }
      25:  
      26:     public boolean search(String s) {
      27:         Node current = root;
      28:         while (current != null) {
      29:             for (int i = 0; i < s.length(); i++) {
      30:                 if (current.subNode(s.charAt(i)) == null)
      31:                     return false;
      32:                 else
      33:                     current = current.subNode(s.charAt(i));
      34:             }/*
      35:              * This means that a string exists, but make sure its a word by
      36:              * checking its 'marker' flag
      37:              */
      38:             if (current.marker == true)
      39:                 return true;
      40:             else
      41:                 return false;
      42:         }
      43:         return false;
      44:     }
      45:  
      46:     public List<String> searchPrefix(String s) {
      47:  
      48:         Node current = root;
      49:         if (current == null) {
      50:             return null;
      51:         }
      52:         List<String> list = new ArrayList<String>();
      53:         Node endNode = null;
      54:         StringBuilder endSB = new StringBuilder();
      55:         for (int i = 0; i < s.length(); i++) {
      56:             if (current.subNode(s.charAt(i)) == null) {
      57:                 endNode = current;
      58:                 break;
      59:             } else {
      60:                 current = current.subNode(s.charAt(i));
      61:                 endNode = current;
      62:                 endSB.append(endNode.content);
      63:             }
      64:         }
      65:         if (endNode == null) {
      66:             return null;
      67:         }
      68:         if (endNode.marker == true) {//  found as a word
      69:             list.add(endSB.toString());
      70:         }
      71:         // depth-first search the sub branch
      72:         Stack<Node> stack = new Stack<Node>();
      73:         stack.push(endNode);
      74:         while (!stack.isEmpty()) {
      75:             Node cur = stack.peek();
      76:             int needCount = cur.child.size();
      77:             for (Node node : cur.child) {
      78:                 if (!node.visited) {
      79:                     node.visited = true;
      80:                     stack.push(node);
      81:                     endSB.append(node.content);
      82:                     if (node.marker) {
      83:                         list.add(endSB.toString());
      84:                     }
      85:                     break;
      86:                 } else {
      87:                     needCount--;
      88:                 }
      89:             }
      90:             if (needCount == 0) {
      91:                 stack.pop();
      92:                 endSB.deleteCharAt(endSB.length()-1);
      93:             }
      94:         }
      95:  
      96:         return list;
      97:     }
      98:  
      99:     public static void main(String[] args) {
     100:         Trie trie = new Trie();
     101:         trie.insert("ball");
     102:         trie.insert("bat");
     103:         trie.insert("dead");
     104:         trie.insert("do");
     105:         trie.insert("doll");
     106:         trie.insert("dork");
     107:         trie.insert("dorm");
     108:         trie.insert("send");
     109:         trie.insert("sense");
     110:         List<String> list = trie.searchPrefix("d");
     111:         for (String s : list) {
     112:             System.out.println(s);
     113:         }
     114:     }
     115: }

    其中構(gòu)建樹的時(shí)候需要不斷的將新詞insert到結(jié)構(gòu)中,search可以接受一個(gè)詞作為輸入,返回這個(gè)詞是否在詞典中。如果只是search來(lái)判斷是否存在,那么hashmap更好的解決這個(gè)問題。trie樹的最大強(qiáng)項(xiàng)是利用前綴檢索,比如想知道一個(gè)詞典中以固定前綴開始的詞有多少,那么prefixsearch可以滿足需求。

    這棵樹可擴(kuò)展的地方太多太多,現(xiàn)有代碼只是一個(gè)鋪墊,對(duì)于任何處理字符的需求,擴(kuò)展屬于自己的特定業(yè)務(wù)場(chǎng)景的trie是個(gè)很不錯(cuò)的選擇。

    本文的實(shí)現(xiàn)是基于http://www.technicalypto.com/2010/04/trie-in-java.html這里實(shí)現(xiàn)的,trie樹截圖也來(lái)源于此,在此對(duì)作者表示感激。

    posted on 2012-08-18 10:10 changedi 閱讀(1727) 評(píng)論(1)  編輯  收藏 所屬分類: 算法

    評(píng)論

    # re: 最簡(jiǎn)Trie的實(shí)現(xiàn) 2012-09-13 16:44 xiaovfight

    插入trie時(shí)應(yīng)該在插入的最后操作中加上字符串結(jié)束的標(biāo)記,也就是吧current.marker = true;加到insert方法的末尾  回復(fù)  更多評(píng)論   

    主站蜘蛛池模板: 亚洲经典在线观看| 亚洲成AV人片高潮喷水| 亚洲精品无码久久久久APP| japanese色国产在线看免费| 99re热精品视频国产免费| 免费鲁丝片一级观看| 亚洲开心婷婷中文字幕| 亚洲综合av一区二区三区不卡| 国产成人高清精品免费观看| 性xxxxx免费视频播放| 亚洲日本一区二区三区在线| wwwxxx亚洲| a毛片在线还看免费网站| 韩国18福利视频免费观看| 久久精品夜色国产亚洲av| 亚洲大码熟女在线观看| 97国产在线公开免费观看| 亚洲成A人片在线观看中文| 亚洲成人高清在线观看| 本道天堂成在人线av无码免费| 亚洲中文无码永久免费| 亚洲av无码av制服另类专区| 美女视频黄.免费网址| 91热成人精品国产免费| 国产亚洲大尺度无码无码专线| 亚洲欧洲日产国码久在线| 久久久久国产精品免费免费不卡| 免费人成在线观看播放国产 | 亚洲国产视频久久| a在线视频免费观看| 免费a在线观看播放| 亚洲午夜精品一区二区公牛电影院| 国产午夜无码片免费| 国产成人免费a在线资源| 国产精品亚洲综合五月天| 久9这里精品免费视频| 亚洲国产免费综合| 亚洲国产乱码最新视频| 99爱在线精品视频免费观看9| 国产福利电影一区二区三区,亚洲国模精品一区 | 18禁成年无码免费网站无遮挡|