数据结构实现
字典树概述与结构体定义
假设有字符串’ac’、‘lx’、‘lyx’和’d’,它们在字典树的存储如下图所示:
首先定义Trie结构体(节点),作为字典树的中的一个节点,该结构各字段的含义:
- 每个Trie结构体中有一个Trie指针数组作为子节点,数组大小为字符串的字符集大小(此处默认为26个小写字母,因此数组大小为26)。若字符集较复杂,可以采用STL库中的map<char, Trie*>来对数据结构进行优化,此处先讨论较简单的情况。
- Trie中的flag字段表示该节点是不是字符串的末尾(图中的红色节点),如果是,则为true。
再定义Dictionary结构体(树),其中包含了一个根节点root,用于表示整棵字典树。
typedef struct {
bool flag;
struct Trie* child[26];
} Trie; // 字典树的一个节点
typedef struct {
Trie* root;
} Dictionary; // 字典树本身
字典树的初始化
字典树节点(Trie)的初始化
首先给定节点Trie的初始化方法。它的思想非常简单:
- 使用malloc分配一段内存空间
- 将子节点初始化为NULL
- 将flag初始化为false
Trie的初始化函数为Trie* buildTrie(),代码如下所示:
Trie* buildTrie() {
// 分配一段内存
Trie* trie = (Trie *) malloc(sizeof(Trie));
int i;
for (i = 0;i < 26; i++){
// 初始化子节点
trie->child[i] = NULL;
}
// 初始化flag
trie->flag = false;
return trie;
}
字典树Dictionary的初始化
再介绍字典树本身Dictionary的初始化方法。这里的初始化指的是,给定字符串集合,将这些字符串都存储在字典树Dictionary中。主要过程如下:
- 为Dictionary分配一段内存(malloc)
- 使用buildTrie() 初始化根节点root
- 遍历字符串集合中的每个字符串s。对于每个s,都从根节点root开始,根据字符创建子节点(若已创建,则直接迭代到该子节点上),向下延伸字典树。
- 当迭代到某节点时,到达字符串的末尾,则将该节点的flag置成true(很重要!!!)
Dictionary的初始化函数如下:
Dictionary* buildDictionaryTree(char ** dictionary, int dictionarySize) {
/*
dictionary:字符串数组的指针
dictionarySize:字符串个数
*/
Dictionary* dic = (Dictionary*) malloc(sizeof(Dictionary));
dic->root = buildTrie();
int i, j;
Trie* cur;
for (i = 0;i < dictionarySize;i++) {
int l = strlen(dictionary[i]);
cur = dic->root;
for (j = 0;j < l;j++) {
int idx = dictionary[i][j] - 'a';
if (!cur->child[idx]) {
cur->child[idx] = buildTrie();
}
cur = cur->child[idx];
}
cur->flag = true;
}
return dic;
}