前缀树的实现

前缀树的实现

何谓前缀树?

前缀树(字典树),使用树状的数据结构存储一个字典的所有单词。前缀树是一个多叉树,一个节点可能有多个子节点,除根结点外,每个节点代表字符串中的一个字符。字符串在前缀树中不一定终止于叶子节点,比如 '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;
    }
};
相关推荐
Genevieve_xiao3 分钟前
【数据结构】【xjtuse】八股文单元小测
数据结构·算法
QT 小鲜肉13 分钟前
【Linux常用命令大全】在 Linux 系统下 Git + Vim编辑器常用指令完全指南(亲测有效)
linux·开发语言·c++·笔记·git·编辑器·vim
Xの哲學13 分钟前
Linux slab分配器深度剖析:从原理到实践
linux·服务器·算法·架构·边缘计算
oioihoii1 小时前
现代C++:一场静默的革命,告别“C with Classes”
c语言·jvm·c++
普通网友2 小时前
C++中的组合模式
开发语言·c++·算法
江公望2 小时前
Qt QByteArray类型,10分钟讲清楚
开发语言·c++·qt
2501_941111462 小时前
C++中的组合模式变体
开发语言·c++·算法
想唱rap2 小时前
Linux下进程的状态和优先级
linux·运维·服务器·开发语言·数据结构·算法
普通网友3 小时前
单元测试在C++项目中的实践
开发语言·c++·算法
Croa-vo3 小时前
逆袭Akuna Quant!美硕秋招亲历,从网申到拿offer全攻略
数据结构·经验分享·算法·面试·职场和发展