前缀树

本文介绍了前缀树(Trie Tree)的概念及其在字符串查询中的应用。通过添加、搜索、删除和前缀查询等操作,展示了如何使用固定数组和哈希表实现前缀树。文章提供了一个具体的Java实现,包括插入、搜索、删除和前缀数量查询的方法,以帮助理解前缀树的工作原理。
摘要由CSDN通过智能技术生成

前缀树

前缀树prefix tree trie

1)单个字符串中,字符从前到后的加到一棵多叉树上

2)字符放在路上,节点上有专属的数据项(常见的是pass和end值)

3)所有样本都这样添加,如果没有路就新建,如有路就复用

4)沿途节点的pass值增加1,每个字符串结束时来到的节点end值增加1

可以完成前缀相关的查询

例子

设计一种结构。用户可以:

1)void insert(String str) 添加某个字符串,可以重复添加,每次算1个

2)int search(String str) 查询某个字符串在结构中还有几个

  1. void delete(String str) 删掉某个字符串,可以重复删除,每次算1个

4)int prefixNumber(String str) 查询有多少个字符串,是以str做前缀的

前缀树路的实现方式

1)固定数组实现

2)哈希表实现

package com.lzf2.class06;

//前缀树
public class TrieTree {

    private Node root;

    public TrieTree() {
        root = new Node();
    }

    /**
     * 添加某个字符串,可以重复添加,每次算1个
     *
     * @param str 要添加的字符串
     */
    public void insert(String str) {
        if (str == null) {
            return;
        }
        Node currNode = root;
        root.pass++;
        char[] chars = str.toCharArray();
        //找路
        for (char c : chars) {
            int path = c - 'a';
            if (currNode.nexts[path] == null) {//没有这条路
                currNode.nexts[path] = new Node();
            }
            currNode = currNode.nexts[path];
            currNode.pass++;
        }
        currNode.end++;
    }

    /**
     * 查询某个字符串在结构中还有几个
     *
     * @param str 要查询的字符串
     * @return 该字符串有几个
     */
    public int search(String str) {
        if (str == null || str.length() == 0) {
            return 0;
        }
        char[] chars = str.toCharArray();
        Node currNode = root;
        for (char c : chars) {
            int path = c - 'a';
            if (currNode.nexts[path] == null) {
                return 0;
            }
            currNode = currNode.nexts[path];
        }
        return currNode.end;
    }

    /**
     * 删掉某个字符串,可以重复删除,每次算1个
     *
     * @param str 要删除的字符串
     */
    public void delete(String str) {
        //1.该字符串是否存在
        if (search(str) == 0) {
            return;
        }
        Node currNode = root;
        currNode.pass--;
        //2.转成字符数据
        char[] chars = str.toCharArray();
        for (char c : chars) {
            int path = c - 'a';
            if (--currNode.nexts[path].pass == 0) {//后面没有其他的字符串了
                currNode.nexts[path] = null;
                return;
            }
            currNode = currNode.nexts[path];
        }
        currNode.end--;
    }

    /**
     * 查询有多少个字符串,是以str做前缀的
     *
     * @param str 要查询的字符串前缀
     * @return 以该str为前缀的个数
     */
    public int prefixNumber(String str) {
        if (str == null || str.length() == 0) {
            return 0;
        }
        Node currNode = root;
        char[] chars = str.toCharArray();
        for (char c : chars) {
            int path = c - 'a';
            if(currNode.nexts[path] == null){
                return 0;
            }
            currNode = currNode.nexts[path];
        }
        return currNode.pass;
    }


    private class Node {
        int pass;//路过的记录数
        int end;//结束的记录数
        Node[] nexts;//路

        public Node() {
            pass = 0;
            end = 0;
            this.nexts = new Node[26];//26个英文字母
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值