实现前缀树

前缀树的实现。包括增加,查询,删除和查询前缀操作。代码中有做较为详细的注释。这里不额外赘述文章相关知识点。

/**
 * 实现前缀树
 */
public class Trie {
    //结点
    class Node{
        //当前结点被经过的次数
        private int pass;
        //当前结点是字符串中最后一个字符时,记录他的次数(当了几次最后一个字符)
        private int end;
        //记录对于下一个结点的指向(路)
        private Node[] nexts;
        //结尾结点标识
        private boolean isEnd;

        //初始化Node
        public Node(){
            pass = 0;
            end = 0;
            isEnd = false;
            //初始化26和字母的空间大小
            nexts = new Node[26];
        }
    }

    //提供一个根结点属性
    private Node root;
    //初始化前缀树
    public Trie(){
        //新建一个根结点
        root = new Node();
    }

    //将字符串挂载到前缀树上
    //参数:字符串  返回值:不需要
    public void insert(String word){
        if("".equals(word) || word == null){
            return ;
        }
        //将字符串变成字符数组  单个操作
        char[] chars = word.toCharArray();
        Node cur = root;
        //将根结点的pass值加加
        cur.pass++;
        //记录当前字符应该在nexts中存储的位置
        int index = 0;
        //循环这个字符数组  将每个字符挂载到前缀树上
        for(int i = 0;i < chars.length;i++){
            //获取存储到nexts中的位置
            index = chars[i] - 'a';
            //判断nexts中是否有当前字符的存在(是否有通往当前字符的路)  如果没有  新建
            if(cur.nexts[index] == null){
                cur.nexts[index] = new Node();
            }
            //移动cur指针
            cur = cur.nexts[index];
            //移动后
            //将当前字符的pass值加加
            cur.pass++;
        }
        //将最后一个结点的end值加加
        cur.end++;
        //当前结点的结尾标识设置为true
        cur.isEnd = true;
    }

    //删除前缀树上给定的字符串
    public void erase(String word){
        //首先  要保证word在前缀树上存在
        if(search(word) != 0){
            //从头结点开始找 一次经过的结点的pass  和  最后一个的end值减去1
            //如果当前结点的pass是0了 则直接将这个结点的空间释放掉
            //将word转成字符串
            char[] chars = word.toCharArray();
            Node cur = root;
            cur.pass--;
            int index = 0;
            for(int i = 0;i < chars.length;i++){
                //获取位置
                index = chars[i] - 'a';
                //减去他的pass
                if (--cur.nexts[index].pass == 0) {
                    //如果当前结点被消耗完毕 直接释放掉
                    //注:这是java的写法,因为JVM中内存会被自动回收,与C++中写法不同
                    cur.nexts[index] = null;
                    return ;
                }
                cur = cur.nexts[index];
            }
            //走到头后 将end减减
            cur.end --;
        }

    }

    //判断字符串是否在前缀树中存在  如果有  返回其出现次数
    //同样的 按照字符来找,如果word找完了 则返回后面一个结点的end值即可
    public int search(String word){
        if("".equals(word) || word == null){
            return 0;
        }
        //word转成字符数组
        char[] chars = word.toCharArray();
        //从根结点开始
        Node cur = root;
        int index = 0;
        for(int i = 0;i < chars.length;i++){
            //获取位置
            index = chars[i] - 'a';
            //判断当前位置上是否有当前字符的存在
            if(cur.nexts[index] == null){
                //如果没有  直接返回
                return 0;
            }
            //如果有  移动指针
            cur = cur.nexts[index];
        }
        //返回word后面一个结点的end值 就是出现次数了
        return cur.end;
    }


    //找出前缀树中 有几个是以prefix作为前缀出现的
    //同样的  直接找出他后面一个结点的出现次数  pass值  即可得到
    public int findCountOfPrefix(String prefix){
        if("".equals(prefix) || prefix == null){
            return 0;
        }
        //将prefix变成字符数组
        char[] chars = prefix.toCharArray();
        //从头结点开始循环遍历数组
        Node cur = root;
        int index = 0;
        for(int i = 0;i < chars.length;i++){
            index = chars[i] - 'a';
            //判断是否存在
            if(cur.nexts[index] == null){
                return 0;
            }
            cur = cur.nexts[index];
        }
        return cur.pass;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值