前缀树的实现

前缀树的实现

何谓前缀树?

前缀树(字典树),使用树状的数据结构存储一个字典的所有单词。前缀树是一个多叉树,一个节点可能有多个子节点,除根结点外,每个节点代表字符串中的一个字符。字符串在前缀树中不一定终止于叶子节点,比如 'app'。如果前缀树路径到达某个节点时表示了一个完整的字符串,那么这个节点应有特殊的标识。一个存储字符串 "apple" "apply" "app" "huw" "oppo" "xiao" "mi" 的前缀树如图:

实现前缀树

实现一个前缀树 Trie ,它有下列操作:

  1. 函数 insert ,在前缀树中添加一个字符串
  2. 函数 search,查找字符串,如果前缀树中包含该字符串则返回 true,否则返回 false。
  3. 函数 startWith,查找字符串前缀。

节点的选择

子节点容器可以选择使用哈希表或数组。

  • 在字符集大小固定且较小的情况下,数组可以提供紧凑的存储,没有额外的哈希表开销。数组可以保持元素有序性以及空间效率比较高。
  • 哈希表比较灵活。

真实的结构:

cpp 复制代码
class TrieNode {
public:
	std::unordered_map<char, TrieNode*> children;
	bool id_end_of_word;
	
	TrieNode() : is_end_of_word(false) {}
};

插入

cpp 复制代码
 void insert(const std::string& word) {
     TrieNode* node = root;
     for (char ch : word) {
         if (node->children.find(ch) == node->children.end()) {
             node->children[ch] = new TrieNode();
         }
         node = node->children[ch];
     }
     node->isEndOfWord = true;
 }

查找

cpp 复制代码
bool search(const std::string& word) {
	TrieNode* node = root;
	for (const auto& ch : word) {
		if (node->children.find(ch) == node->children.end()) return false;
		node = node->children[ch];
	}
	return node->is_end_of_word;
}

查找前缀

查找前缀与查找差别在于:可以直接返回 true。

cpp 复制代码
bool startWith(const std::string& word) {
	TrieNode* node = root;
	for (const auto& ch : word) {
		if (node->children.find(ch) == node->children.end()) return false;
		node = node->children[ch];
	}
	return true;
}

完整代码

cpp 复制代码
class Trie {
private:
    TrieNode* root;
    
public:
    Trie() {
        root = new TrieNode();
    }
    
    void insert(const std::string& word) {
        TrieNode* node = root;
        for (char ch : word) {
            if (node->children.find(ch) == node->children.end()) {
                node->children[ch] = new TrieNode();
            }
            node = node->children[ch];
        }
        node->isEndOfWord = true;
    }
    
    bool search(const std::string& word) const {
        TrieNode* node = root;
        for (char ch : word) {
            if (node->children.find(ch) == node->children.end()) {
                return false;
            }
            node = node->children[ch];
        }
        return node->isEndOfWord;
    }
};
相关推荐
sali-tec7 小时前
C# 基于halcon的视觉工作流-章66 四目匹配
开发语言·人工智能·数码相机·算法·计算机视觉·c#
小明说Java7 小时前
常见排序算法的实现
数据结构·算法·排序算法
45288655上山打老虎7 小时前
C++完美转发
java·jvm·c++
行云流水20198 小时前
编程竞赛算法选择:理解时间复杂度提升解题效率
算法
SunkingYang9 小时前
程序崩溃闪退——MFC共享内存多次OpenFileMapping和MapViewOfFile而没有相应的UnmapViewOfFile和CloseHandle
c++·mfc·共享内存·崩溃·闪退·close·openfilemapping
问君能有几多愁~9 小时前
C++ 日志实现
java·前端·c++
smj2302_796826529 小时前
解决leetcode第3768题.固定长度子数组中的最小逆序对数目
python·算法·leetcode
JANGHIGH9 小时前
c++ 多线程(二)
开发语言·c++
珑墨10 小时前
【浏览器】页面加载原理详解
前端·javascript·c++·node.js·edge浏览器
cynicme10 小时前
力扣3531——统计被覆盖的建筑
算法·leetcode