前缀树

什么是前缀树

  • 前缀树又叫单词查找树,Tire树,是哈希树的变种。典型应用于统计,排序和保存大量字符串,经常被搜索引擎系统用于文本词频统计。
  • 前缀树的每一个节点会有多个子节点,通往不同子节点的路径上有着不同的字符串(不仅限于字符串)。
  • 优点:可以利用字符串的公共前缀来减少查询时间,最大限度地减少不必要的字符串比较,查询效率比哈希树高。

问题举例
一个字符串类型的数组arr1,另一个字符串类型数组arr2。
(1)arr2中有哪些字符串,是arr1中出现的?请打印。
(2)arr2中有哪些字符串,是作为arr1中某个字符串前缀出现的?请打印。
(3)arr2中有哪些字符串,是作为arr1中某个字符串前缀出现的?请打印arr2中出现次数最大的前缀。
构造前缀树
下面以数组String[] arr1={“ab”,“abc”,“bcde”,“aab”}; 为例构造一个前缀树

1.加入"ab"

2.加入"abc"

3.加入"bcde"

4.加入"aab"

前缀树的代码实现

public class TrieDemo {
    public static void main(String[] args) {
        String[] arr1={"ab","abc","bcde"};
        TrieTree trieTree = new TrieTree();
        trieTree.add("abc");
        trieTree.add("abc");
        trieTree.add("abcd");
        trieTree.add("abcde");
        trieTree.delete("abc");
        int num = trieTree.search("abc");
        System.out.println("num="+num);
        int prefixNumber = trieTree.prefixNumber("abc");
        System.out.println("prefixNumber="+prefixNumber);
    }
    //先构造一个类表示前缀树的结点
    public static class TrieNode {
        int path;  //path表示经过这个结点的字符串个数(这个值不包含以这个结点为终点的字符串)
        int end;   //end表示在这个结点结束的字符串的个数
        TrieNode[] nexts;

        public TrieNode() {
            this.path = 0; 
            this.end = 0;  
            nexts = new TrieNode[26];
        }

    }

    //构造一个类表示前缀树
    public static class TrieTree {
        TrieNode root;

        public TrieTree() {
            //初始化根结点
            this.root = new TrieNode();
        }

        //1.加入字符串的方法
        public void add(String str) {
            char[] chars = str.toCharArray();
            TrieNode node = root;
            int index = 0;
            for (int i = 0; i < chars.length; i++) {
                index = chars[i] - 'a';
                if (node.nexts[index] == null) { //说明没有这个结点
                    //创建一个新的结点
                    TrieNode trieNode = new TrieNode();
                    //让当前结点的nexts对应的结点指向这个新的结点
                    node.nexts[index] = trieNode;
                }
                //往下走,当前的node变成下一个node
                node = node.nexts[index];
                //把这个node的path+1
                node.path++;
            }
            node.end++;
        }
        //2.查询前缀树中有几个这样的字符串
        public int search(String str) {
            if(str==null||str==""){
                return 0;
            }
            char[] chars = str.toCharArray();
            int index = 0;
            TrieNode node = root;
            for (int i = 0; i < chars.length; i++) {
                index = chars[i] - 'a';
                //如果找查找过程中node.nexts[index]为空表示chars还没有遍历完,说明树中没有这个字符串
                if (node.nexts[index] == null) {
                    return 0;
                }
                node = node.nexts[index];
            }
            return node.end;
        }
        //3.删除字符串的方法
        public void delete(String str) {
            //1.先查询树中是否有这样一个字符串
            //说明树中没有这样一个字符串
            if (search(str) == 0) {
                return;
            }
            TrieNode node = root;
            char[] chars = str.toCharArray();
            int index = 0;
            for (int i = 0; i < chars.length; i++) {
                index = chars[i] - 'a';
                if (node.nexts[index].path == 0) { //这个时候说明node.nexts[index]这个结点上已经没有数据了,删除这个结点
                    node.nexts[index] = null;
                    return;
                }
                node = node.nexts[index];
                node.path--;
            }
            node.end--;
        }


        //4.查询前缀树中有多少个以prefix为前缀的字符串
        public int prefixNumber(String prefix) {
            if (prefix == "" || prefix == null) {
                return 0;
            }
            char[] chars = prefix.toCharArray();
            int index = 0;
            TrieNode node = root;
            for (int i = 0; i < chars.length; i++) {
                index = chars[i] - 'a';
                if (node.nexts[index] == null) {
                    return 0;
                }
                node = node.nexts[index];
            }
            return node.path;
        }
    }

}

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值