前缀树(java代码实现)

package class05;

import java.util.HashMap;

// 该程序完全正确
public class Code02_TrieTree {

   public static class Node1 {
      public int pass;
      public int end;
      public Node1[] nexts;

      public Node1() {
         pass = 0;
         end = 0;
         // 0    a
         // 1    b
         // 2    c
         // ..   ..
         // 25   z
         // nexts[i] == null   i方向的路不存在
         // nexts[i] != null   i方向的路存在
         nexts = new Node1[26];
      }
   }

   public static class Trie1 {
      private Node1 root;

      public Trie1() {
         root = new Node1();
      }

      public void insert(String word) {
         if (word == null) {
            return;
         }
         char[] str = word.toCharArray();
         Node1 node = root;
         node.pass++;
         int path = 0;
         for (int i = 0; i < str.length; i++) { // 从左往右遍历字符
            path = str[i] - 'a'; // 由字符,对应成走向哪条路
            if (node.nexts[path] == null) {
               node.nexts[path] = new Node1();
            }
            node = node.nexts[path];
            node.pass++;
         }
         node.end++;
      }

      public void delete(String word) {
         if (search(word) != 0) {
            char[] chs = word.toCharArray();
            Node1 node = root;
            node.pass--;
            int path = 0;
            for (int i = 0; i < chs.length; i++) {
               path = chs[i] - 'a';
               if (--node.nexts[path].pass == 0) {
                  node.nexts[path] = null;
                  return;
               }
               node = node.nexts[path];
            }
            node.end--;
         }
      }

      // word这个单词之前加入过几次
      public int search(String word) {
         if (word == null) {
            return 0;
         }
         char[] chs = word.toCharArray();
         Node1 node = root;
         int index = 0;
         for (int i = 0; i < chs.length; i++) {
            index = chs[i] - 'a';
            if (node.nexts[index] == null) {
               return 0;
            }
            node = node.nexts[index];
         }
         return node.end;
      }

      // 所有加入的字符串中,有几个是以pre这个字符串作为前缀的
      public int prefixNumber(String pre) {
         if (pre == null) {
            return 0;
         }
         char[] chs = pre.toCharArray();
         Node1 node = root;
         int index = 0;
         for (int i = 0; i < chs.length; i++) {
            index = chs[i] - 'a';
            if (node.nexts[index] == null) {
               return 0;
            }
            node = node.nexts[index];
         }
         return node.pass;
      }
   }

   public static class Node2 {
      public int pass;
      public int end;
      public HashMap<Integer, Node2> nexts;

      public Node2() {
         pass = 0;
         end = 0;
         nexts = new HashMap<>();
      }
   }

   public static class Trie2 {
      private Node2 root;

      public Trie2() {
         root = new Node2();
      }

      public void insert(String word) {
         if (word == null) {
            return;
         }
         char[] chs = word.toCharArray();
         Node2 node = root;
         node.pass++;
         int index = 0;
         for (int i = 0; i < chs.length; i++) {
            index = (int) chs[i];
            if (!node.nexts.containsKey(index)) {
               node.nexts.put(index, new Node2());
            }
            node = node.nexts.get(index);
            node.pass++;
         }
         node.end++;
      }

      public void delete(String word) {
         if (search(word) != 0) {
            char[] chs = word.toCharArray();
            Node2 node = root;
            node.pass--;
            int index = 0;
            for (int i = 0; i < chs.length; i++) {
               index = (int) chs[i];
               if (--node.nexts.get(index).pass == 0) {
                  node.nexts.remove(index);
                  return;
               }
               node = node.nexts.get(index);
            }
            node.end--;
         }
      }

      // word这个单词之前加入过几次
      public int search(String word) {
         if (word == null) {
            return 0;
         }
         char[] chs = word.toCharArray();
         Node2 node = root;
         int index = 0;
         for (int i = 0; i < chs.length; i++) {
            index = (int) chs[i];
            if (!node.nexts.containsKey(index)) {
               return 0;
            }
            node = node.nexts.get(index);
         }
         return node.end;
      }

      // 所有加入的字符串中,有几个是以pre这个字符串作为前缀的
      public int prefixNumber(String pre) {
         if (pre == null) {
            return 0;
         }
         char[] chs = pre.toCharArray();
         Node2 node = root;
         int index = 0;
         for (int i = 0; i < chs.length; i++) {
            index = (int) chs[i];
            if (!node.nexts.containsKey(index)) {
               return 0;
            }
            node = node.nexts.get(index);
         }
         return node.pass;
      }
   }

   public static class Right {

      private HashMap<String, Integer> box;

      public Right() {
         box = new HashMap<>();
      }

      public void insert(String word) {
         if (!box.containsKey(word)) {
            box.put(word, 1);
         } else {
            box.put(word, box.get(word) + 1);
         }
      }

      public void delete(String word) {
         if (box.containsKey(word)) {
            if (box.get(word) == 1) {
               box.remove(word);
            } else {
               box.put(word, box.get(word) - 1);
            }
         }
      }

      public int search(String word) {
         if (!box.containsKey(word)) {
            return 0;
         } else {
            return box.get(word);
         }
      }

      public int prefixNumber(String pre) {
         int count = 0;
         for (String cur : box.keySet()) {
            if (cur.startsWith(pre)) {
               count += box.get(cur);
            }
         }
         return count;
      }
   }

   // for test
   public static String generateRandomString(int strLen) {
      char[] ans = new char[(int) (Math.random() * strLen) + 1];
      for (int i = 0; i < ans.length; i++) {
         int value = (int) (Math.random() * 6);
         ans[i] = (char) (97 + value);
      }
      return String.valueOf(ans);
   }

   // for test
   public static String[] generateRandomStringArray(int arrLen, int strLen) {
      String[] ans = new String[(int) (Math.random() * arrLen) + 1];
      for (int i = 0; i < ans.length; i++) {
         ans[i] = generateRandomString(strLen);
      }
      return ans;
   }

   public static void main(String[] args) {
      int arrLen = 100;
      int strLen = 20;
      int testTimes = 100000;
      for (int i = 0; i < testTimes; i++) {
         String[] arr = generateRandomStringArray(arrLen, strLen);
         Trie1 trie1 = new Trie1();
         Trie2 trie2 = new Trie2();
         Right right = new Right();
         for (int j = 0; j < arr.length; j++) {
            double decide = Math.random();
            if (decide < 0.25) {
               trie1.insert(arr[j]);
               trie2.insert(arr[j]);
               right.insert(arr[j]);
            } else if (decide < 0.5) {
               trie1.delete(arr[j]);
               trie2.delete(arr[j]);
               right.delete(arr[j]);
            } else if (decide < 0.75) {
               int ans1 = trie1.search(arr[j]);
               int ans2 = trie2.search(arr[j]);
               int ans3 = right.search(arr[j]);
               if (ans1 != ans2 || ans2 != ans3) {
                  System.out.println("Oops!");
               }
            } else {
               int ans1 = trie1.prefixNumber(arr[j]);
               int ans2 = trie2.prefixNumber(arr[j]);
               int ans3 = right.prefixNumber(arr[j]);
               if (ans1 != ans2 || ans2 != ans3) {
                  System.out.println("Oops!");
               }
            }
         }
      }
      System.out.println("finish!");

   }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
字典树的Java实现可以使用递归来构建。首先需要定义一个TrieNode类,其中包含一个Map用于存储子节点,以及一个布尔值表示当前节点是否是一个单词的结尾。然后,定义一个Trie类来维护根节点。在Trie类中实现insert、search和startsWith方法。 下面是一个简单的字典树Java代码实现示例: ```java class TrieNode { Map<Character, TrieNode> children; boolean isEndOfWord; public TrieNode() { children = new HashMap<>(); isEndOfWord = false; } } class Trie { private TrieNode root; public Trie() { root = new TrieNode(); } public void insert(String word) { TrieNode current = root; for (int i = 0; i < word.length(); i++) { char ch = word.charAt(i); TrieNode node = current.children.get(ch); if (node == null) { node = new TrieNode(); current.children.put(ch, node); } current = node; } current.isEndOfWord = true; } public boolean search(String word) { TrieNode current = root; for (int i = 0; i < word.length(); i++) { char ch = word.charAt(i); TrieNode node = current.children.get(ch); if (node == null) { return false; } current = node; } return current.isEndOfWord; } public boolean startsWith(String prefix) { TrieNode current = root; for (int i = 0; i < prefix.length(); i++) { char ch = prefix.charAt(i); TrieNode node = current.children.get(ch); if (node == null) { return false; } current = node; } return true; } } ``` 这是一个简单的Trie字典树的Java代码实现,其中包括了插入、查询和查询前缀三个常用操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值