跟左神学算法8 进阶数据结构(前缀树)

内容:

1、前缀树详解

2、如何生成前缀树

3、前缀树应用

1、前缀树详解

什么是前缀树:

前缀树又称字典树、Trie树,是一种树形结构,是哈希树的变种,是一种用于快速检索的多叉树结构
典型应用是用于统计和排序大量的字符串(不限于字符串),经常被搜索引擎系统用作文本词频统计
优点是可以最大限度地减少无谓地字符串比较,查询效率高

前缀树的特点:

  • 根节点不包含字符,除根节点外的每一个子节点都包含一个字符
  • 从根节点到某一节点的路径上的路径上的字符连接起来就是该节点对应的字符串
  • 每个节点的所有子节点包含的字符都不相同

2、如何生成前缀树

前缀树:实际上就是一个森林

生成前缀树:

  1 public class trieTree{    
  2     // the node of trie
  3     public static class TrieNode {
  4         // path: string arrive the node
  5         // end: string end in the node
  6         // nexts: next nodes
  7         public int path;
  8         public int end;
  9         public HashMap<Character, TrieNode> nexts;
 10 
 11         public TrieNode() {
 12             path = 0;
 13             end = 0;
 14             nexts = new HashMap<Character, TrieNode>();
 15         }
 16     }
 17     
 18     
 19     // the trie
 20     public static class Trie {
 21         private TrieNode root;        // the root of trie
 22 
 23         public Trie() {
 24             root = new TrieNode();
 25         }
 26 
 27         // insert a word to a trie
 28         public void insert(String word) {
 29             if (word == null) {
 30                 return;
 31             }
 32             char index;
 33             char[] chs = word.toCharArray();
 34             TrieNode node = root;
 35             for (int i = 0; i < chs.length; i++) {
 36                 index = chs[i];
 37                 if (node.nexts.get(index) == null) {
 38                     node.nexts.put(index, new TrieNode());
 39                 }
 40                 node = node.nexts.get(index);
 41                 node.path++;
 42             }
 43             node.end++;
 44         }
 45         
 46         // search a word in a trie(similar to insert)
 47         public int search(String word) {
 48             if (word == null) {
 49                 return 0;
 50             }
 51             char index;
 52             char[] chs = word.toCharArray();
 53             TrieNode node = root;
 54             for (int i = 0; i < chs.length; i++) {
 55                 index = chs[i];
 56                 if (node.nexts.get(index) == null) {
 57                     return 0;
 58                 }
 59                 node = node.nexts.get(index);
 60             }
 61             return node.end;
 62         }
 63 
 64         // delete a word to a trie(similar to insert)
 65         public void delete(String word) {
 66             if(search(word) != 0){
 67                 char index;
 68                 char[] chs = word.toCharArray();
 69                 TrieNode node = root;
 70                 for (int i = 0; i < chs.length; i++) {
 71                     index = chs[i];
 72                     if (--node.nexts.get(index).path == 0) {
 73                         node.nexts.remove(index);
 74                         return;
 75                     }
 76                     node = node.nexts.get(index);
 77                 }
 78                 node.end--;
 79             }
 80         }
 81         
 82         // get the pre in trie's fixNumber(similar to search)
 83         public int prefixNumber(String pre){
 84             if(pre==null){
 85                 return 0;
 86             }
 87             char index;
 88             char[] chs = pre.toCharArray();
 89             TrieNode node = root;
 90             for (int i = 0; i < chs.length; i++) {
 91                 index = chs[i];
 92                 if (node.nexts.get(index) == null) {
 93                     return 0;
 94                 }
 95                 node = node.nexts.get(index);
 96             }
 97             return node.path;
 98         }    
 99     }
100 }

3、前缀树应用

问题描述:

1、arr2中有哪些字符,是arr1中出现的?请打印
2、arr2中有哪些字符,是作为arr1中某个字符串前缀出现的?请打印
3、arr2中有哪些字符,是作为arr1中某个字符串前缀出现的?请打印arr2中出现次数最大的前缀

解决思路:

借助上述实现的前缀树

代码:

 1 Trie trie = new Trie();
 2 for(int i=0; i<arr1.length; i++){
 3     trie.insert(arr1[i]);
 4 }
 5 
 6 // 打印arr2中出现在arr1中的字符串
 7 for(int i=0; i<arr2.length; i++){
 8     if(trie.search(arr2[i]) != 0){
 9         System.out.print(arr2[i] + " ");
10     }
11 }
12 System.out.println();
13 
14 // 打印arr2中作为arr1中某个字符串前缀出现的字符串
15 for(int i=0; i<arr2.length; i++){
16     if(trie.prefixNumber(arr2[i]) != 0){
17         System.out.print(arr2[i] + " ");
18     }
19 }
20 System.out.println();
21 
22 // 打印arr2中作为arr1中某个字符串前缀出现次数最大的字符串
23 int index = -1, max = 0;
24 for(int i=0; i<arr2.length; i++){
25     int times = trie.prefixNumber(arr2[i]);
26     if(times > max){
27         max = times;
28         index = i;
29     }
30 }
31 System.out.println(arr2[index]);
32 System.out.println();
原文地址:https://www.cnblogs.com/wyb666/p/10195322.html