题目:
实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。
示例:
Trie trie = new Trie();
trie.insert(“apple”);
trie.search(“apple”); // 返回 true
trie.search(“app”); // 返回 false
trie.startsWith(“app”); // 返回 true
trie.insert(“app”);
trie.search(“app”); // 返回 true
说明:
你可以假设所有的输入都是由小写字母 a-z 构成的。
保证所有输入均为非空字符串。
解题思路:
维护一个结构体,通过结构体中的结构体数组指针相连接,每一个结构体连接条即为一个单词;
因为前缀树为字符串,故只需要申请26个字符长度即可。
#include <string.h>
#define NUM 26
typedef struct {
int isWord;
struct Trie *nextList[NUM];
} Trie;
/** Initialize your data structure here. */
Trie* trieCreate() {
//申请内存,并进行初始化
Trie *root = (Trie *)calloc(1, sizeof(Trie));
return root;
}
/** Inserts a word into the trie. */
void trieInsert(Trie* obj, char * word)
{
//将word中的每一个字符都放进去
Trie *root = obj;
int len = strlen(word);
for (int i = 0; i < len; i++) {
int id = word[i] - 'a';
//不存在则分配内存
if (root ->nextList[id] == NULL) {
root->nextList[id] = trieCreate();
}
//继续向下走
root = root -> nextList[id];
}
root ->isWord = true;
}
/** Returns if the word is in the trie. */
bool trieSearch(Trie* obj, char * word) {
Trie *root = obj;
int len = strlen(word);
for (int i = 0; i < len; i++) {
int id = word[i] - 'a';
if (root ->nextList[id] == NULL) {
return false;
}
//继续向下走
root = root -> nextList[id];
}
return root -> isWord;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool trieStartsWith(Trie* obj, char * prefix)
{
Trie *root = obj;
int len = strlen(prefix);
for (int i = 0; i < len; i++) {
int id = prefix[i] - 'a';
if (root ->nextList[id] == NULL) {
return false;
}
//继续向下走
root = root -> nextList[id];
}
return true;
}
void trieFree(Trie* obj)
{
Trie *root = obj;
for (int i = 0; i < NUM; i++) {
if (root -> nextList[i] == NULL) {
continue;
}
//递归释放,如果只释放单一节点,会造成该根节点下的子节点未释放,会造成内存泄露
return trieFree(root -> nextList[i]);
}
free(root);
}
/**
* Your Trie struct will be instantiated and called as such:
* Trie* obj = trieCreate();
* trieInsert(obj, word);
* bool param_2 = trieSearch(obj, word);
* bool param_3 = trieStartsWith(obj, prefix);
* trieFree(obj);
*/