数据结构实现 8.1:字典树(C++版)
1. 概念及基本框架
字典树 顾名思义,就是用来存放单词的树,也称 Trie树 ,其本质上是一种多叉树,我们可以通过图示说明。
这里有一个灰色的根结点,不存储信息,然后下面的每个结点存储一个字母,利用结点颜色区分从根结点到当前结点构成的字符串是否是一个单词。这样,就可以构成一部字典。很显然,从字典中查找一个单词,与字典 的容量并无关系,而只与单词长度有关。这样只要建立好了字典,那么可以大大减小查找操作的时间复杂度。
当然,我们也可以把字母存储在路径上,只用结点颜色表示当前结点构成的字符串是否是一个单词。
我们先来定义一个字典树的结点,代码如下:
class TrieNode{
public:
TrieNode(bool isWord = false){
this->isWord = isWord;
BSTMap<char, TrieNode*> *p = new BSTMap<char, TrieNode*>;
next = p;
}
TrieNode operator= (TrieNode& node){
this->isWord = node.isWord;
this->next = node.next;
return *this;
}
public:
bool isWord;
BSTMap<char, TrieNode*> *next;
};
这里使用了我们之前实现的 map 作为结点,其中 key 作为字母,value 用来存储子树。(很显然,每个结点都可以看成一棵多叉树的根)isWord 表示是否是一个单词,初始化默认为 false 。这里对 = 运算符进行了重载,方便我们后面的操作。
有了结点,字典树的大体框架如下:
class Trie{
public:
Trie(){
m_size = 0;
}
...
private:
TrieNode root;
int m_size;
};
root 表示字典树的根,不存储信息。
m_size 表示字典树的大小。
同样,为了保护数据,这些变量都放在 private 区。
接下来我们就对字典树的增加、查询以及一些其他基本操作用代码去实现。
2. 基本操作程序实现
2.1 增加操作
class Trie{
public:
...
void add(std::string word){
TrieNode* cur = &root;
for (int i = 0; i < word.size