Trie树-Java实现

Trie树,又称单词查找树,是一种树形结构。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比较高。 

       基本性质:

  1.   根节点不包含字符,除根节点外每一个节点都只包含一个字符。
  2.   从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
  3.   每个节点的所有子节点包含的字符都不相同。

       核心思想:空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。

       优点:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

       缺点:基于空间换时间的思想,所以系统中若存在大量的没有公共前缀的字符串则会消耗大量内存。

       应用场景:第一:词频统计;第二: 前缀匹配;第三:去重

实现代码:

  1 /**
  2  * Created by hardaway on 2018/7/26.
  3  */
  4 public class Trie
  5 {
  6     private int SIZE=26;
  7     private TrieNode root;//字典树的根
  8 
  9     Trie() //初始化字典树
 10     {
 11         root=new TrieNode();
 12     }
 13 
 14     private class TrieNode //字典树节点
 15     {
 16         private int num;//有多少单词通过这个节点,即由根至该节点组成的字符串模式出现的次数
 17         private TrieNode[]  son;//所有的儿子节点
 18         private boolean isEnd;//是不是最后一个节点
 19         private char val;//节点的值
 20         private int count; ///有多少单词以此字符结尾
 21 
 22         TrieNode()
 23         {
 24             num=1;
 25             son=new TrieNode[SIZE];
 26             isEnd=false;
 27         }
 28     }
 29 
 30     //建立字典树
 31     public void insert(String str) //在字典树中插入一个单词
 32     {
 33         if(str==null||str.length()==0)
 34         {
 35             return;
 36         }
 37         TrieNode node=root;
 38         char[] letters=str.toCharArray();
 39         for(int i=0,len=str.length(); i<len; i++)
 40         {
 41             int pos=letters[i]-'a';
 42             if(node.son[pos]==null)
 43             {
 44                 node.son[pos]=new TrieNode();
 45                 node.son[pos].val=letters[i];
 46             }
 47             else
 48             {
 49                 node.son[pos].num++;
 50             }
 51             node=node.son[pos];
 52         }
 53         node.isEnd=true;
 54         node.count=node.count+1;
 55     }
 56 
 57     //计算单词前缀的数量
 58     public int countPrefix(String prefix)
 59     {
 60         if(prefix==null||prefix.length()==0)
 61         {
 62             return-1;
 63         }
 64         TrieNode node=root;
 65         char[]letters=prefix.toCharArray();
 66         for(int i=0,len=prefix.length(); i<len; i++)
 67         {
 68             int pos=letters[i]-'a';
 69             if(node.son[pos]==null)
 70             {
 71                 return 0;
 72             }
 73             else
 74             {
 75                 node=node.son[pos];
 76             }
 77         }
 78         return node.num;
 79     }
 80     //打印指定前缀的单词
 81     public List<String> hasPrefix(String prefix)
 82     {
 83         if (prefix == null || prefix.length() == 0)
 84         {
 85             return null;
 86         }
 87         TrieNode node = root;
 88         char[] letters = prefix.toCharArray();
 89         for (int i = 0, len = prefix.length(); i < len; i++)
 90         {
 91             int pos = letters[i] - 'a';
 92             if (node.son[pos] == null)
 93             {
 94                 return null;
 95             }
 96             else
 97             {
 98                 node = node.son[pos];
 99             }
100         }
101         List<String> list = new LinkedList<String>();
102         preTraverse(node, prefix,list);
103         return list;
104     }
105     // 遍历经过此节点的单词.
106     public void preTraverse(TrieNode node, String prefix, List<String> list) {
107         if(node.isEnd)
108             list.add(prefix);
109         for (TrieNode child : node.son) {
110             if (child != null) {
111                 preTraverse(child, prefix + child.val, list);
112             }
113         }
114     }
115 
116     //在字典树中查找一个完全匹配的单词.
117     public boolean has(String str)
118     {
119         if(str==null||str.length()==0)
120         {
121             return false;
122         }
123         TrieNode node=root;
124         char[]letters=str.toCharArray();
125         for(int i=0,len=str.length(); i<len; i++)
126         {
127             int pos=letters[i]-'a';
128             if(node.son[pos]!=null)
129             {
130                 node=node.son[pos];
131             }
132             else
133             {
134                 return false;
135             }
136         }
137         return node.isEnd;
138     }
139 
140     //在字典树中查找一个完全匹配的单词的出现次数
141     public int count(String str)
142     {
143         if(str==null||str.length()==0)
144         {
145             return 0;
146         }
147         TrieNode node=root;
148         char[]letters=str.toCharArray();
149         for(int i=0,len=str.length(); i<len; i++)
150         {
151             int pos=letters[i]-'a';
152             if(node.son[pos]!=null)
153             {
154                 node=node.son[pos];
155             }
156             else
157             {
158                 return 0;
159             }
160         }
161         if(node.isEnd)
162             return node.count;
163         return 0;
164     }
165 
166     //前序遍历字典树.
167     public void preTraverse(TrieNode node)
168     {
169         if(node!=null)
170         {
171             System.out.print(node.val+"-");
172             for(TrieNode child:node.son)
173             {
174                 preTraverse(child);
175             }
176         }
177     }
178 
179     public TrieNode getRoot()
180     {
181         return this.root;
182     }
183 
184     public static void main(String[]args)
185     {
186         Trie tree=new Trie();
187         String[]strs= {"banana","band","bee","absolute","acm","band"};
188         String[]prefix= {"ba","b","band","abc",};
189         for(String str:strs)
190         {
191             tree.insert(str);
192         }
193         System.out.println(tree.has("ban"));
194         System.out.println(tree.count("band"));
195         tree.preTraverse(tree.getRoot());
196         System.out.println();
197         for(String pre:prefix)
198         {
199             int num=tree.countPrefix(pre);
200             System.out.println(pre+":   "+num);
201         }
202         System.out.println(tree.hasPrefix("ba"));
203 
204     }
205 }

ref :  https://www.cnblogs.com/yangjiannr/p/Trie-tree.html

 https://blog.csdn.net/u012605629/article/details/40428987

http://acm.hdu.edu.cn/showproblem.php?pid=1251

猜你喜欢

转载自www.cnblogs.com/hardaway/p/9374532.html