Trie

本文详细介绍了Trie字典树的数据结构及其应用,包括添加、查询和前缀搜索操作。Trie通过优化字符串的存储方式,实现了快速查找和避免重复,适用于大量字符串的集合。此外,还探讨了Trie在模式匹配和字符串映射问题中的实现,以及如何在Trie上进行删除操作。示例代码展示了Trie节点的定义、插入和查找功能,进一步阐述了其在LeetCode题目中的实际应用。
摘要由CSDN通过智能技术生成

Trie

1、Trie字典树(前缀树)

字典:映射;Trie专门用来处理字符串

字典:如果有n个条目,使用树结构,查询的时间复杂度是O(logn)

Trie:查询每个条目的时间复杂度,和字典中一共有多少条目无关。O(w),w为查询单词的长度。

在这里插入图片描述

每个节点有若干个指向下个节点的指针,考虑不同的语言、不同的情景,如英文有26个指针。

class Node{

​ char c;//可以不存储

Map<char,Node> next;

}-----------》

class Node{

​ boolean isWord;//标识是否是一个单词的结尾

​ Map<char,Node> next;

}

2、Trie基础

n叉树:使用Map

public class Trie{}

(1)内部类Node

private class Node{
	public boolean isWord;
    public TreeMap<Character,Node> next;
    //构造函数
    public Node(boolean isWord) {
		this.isWord=isWord;
		next=new TreeMap<>();
	}
	public Node() {
		this(false);
	}
}

(2) class Trie变量

private Node root;
private int size
//构造函数

(3)向trie中添加元素

public void add(String word) {
		Node cur=root;
		for(int i=0;i<word.length();i++) {
			char c=word.charAt(i);
			if(cur.next.get(c)==null)
				cur.next.put(c, new Node());
			cur=cur.next.get(c);
		}
		if(!cur.isWord) {
			cur.isWord=true;
			size++;
		}
}

Trie与集合:向Trie中添加元素时,也不会添加重复的字符串,这与集合结构非常类似,但集合可以存储任何可比较的元素。

也可以在Trie的声明中添加一个域,若isWord为True时,增加释义或统计词频,这样就构成了映射结构。

3、Trie字典树的查询

//查询单词word是否在Trie中
public boolean contains(String word) {
    Node cur=root;
    for(int i=0;i<word.length();i++) {
        char c=word.charAt(i);
        if(cur.next.get(c)==null)
            return false;
        cur=cur.next.get(c);
    }
    return cur.isWord;
}

4、Trie字典树前缀查询

//查询是否在Trie中有单词一prefix为前缀
public boolean isPrefix(String prefix) {
    Node cur=root;
    for(int i=0;i<prefix.length();i++) {
        char c=prefix.charAt(i);
        if(cur.next.get(c)==null)
            return false;
        cur=cur.next.get(c);
    }
    return true;
}

leetcode208:实现Trie

?是否能在二分搜索树实现isPrefix

5、Trie字典树和简单的模式匹配

leetcode211:设计一个数据结构,支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。

核心代码:

public boolean search(String word) {
    return match(root,word,0);
}
private boolean match(Node node,String word,int index) {
    if(index==word.length())
        return node.isWord;
    char c=word.charAt(index);
    if(c!='.') {
        if(node.next.get(c)==null)
            return false;
        return match(node.next.get(c),word,index+1);
    }
    else {
        for(char nextChar:node.next.keySet())
            if(match(node.next.get(nextChar),word,index+1))
                return true;
        return false;
    }
}

6、Trie字典树和字符串映射

计算包含特定前缀的所有键的值的总和。

遍历node及node节点的所有子树,返回这个总和。

核心代码

import java.util.TreeMap;
public class Solution677 {
	private class Node{
		public int value;
		public TreeMap<Character,Node> next;
		public Node(int value) {
			this.value=value;
			next=new TreeMap<>();
		}
		public Node() {
			this(0);
		}
	}
	private Node root;
	public Solution677() {
		root=new Node();
	}
	public void insert(String key,int val) {
		Node cur=root;
		for(int i=0;i<key.length();i++) {
			char c=key.charAt(i);
			if(cur.next.get(c)==null)
				cur.next.put(c, new Node());
			cur=cur.next.get(c);
		}
		cur.value=val;
	}
	public int sum(String prefix) {
		Node cur=root;
		for(int i=0;i<prefix.length();i++) {
			char c=prefix.charAt(i);
			if(cur.next.get(c)==null)
				return 0;
			cur=cur.next.get(c);
		}
		return sum(cur);
	}
	private int sum(Node node) {
        //if(node.next.size()==0)
        //	return node.value;
		int res=node.value;
		for(char c:node.next.keySet())
			res+=sum(node.next.get(c));
		return res;
	}
}

7、Trie删除

三种情况

(1)如果待删除的单词是另一个单词的前缀,只需要把该单词的最后一个节点的 isWord 的改成false

(2)如果单词的所有字母的都没有多个分支(也就是说该单词所有的字符对应的Node都只有一个子节点),则删除整个单词

(3)如果单词的除了最后一个字母,其他的字母有多个分支 …

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值