Trie树
主要参照严蔚敏《数据结构》书中给出的结构来实现。但是不同之处是没有对叶子节点进行压缩,每个节点的类型都是一样的,这是与书中不同之处。
本文主要是提供实现思路,Trie的定义还是看书吧:
参考书:数据结构-严蔚敏
位置:P247-251
提取密码:8u05
c++实现
定义了Trie树的结构,目前仅可以输入小写字母
typedef struct TrieNode {
TrieNode* children[ALPHABETA];
//以该节点结尾是否为单词
bool isWord;
};
实现了四个主要方法:
1.插入
2.查询
3.删除
4.显示所有
完整代码
#include <iostream>
#include <string>
using namespace std;
//输入字符串的最大长度
const int STRMAXLENTH=20;
//可以存26个字母(大写或者小写)
const int ALPHABETA=26;
typedef struct TrieNode {
TrieNode* children[ALPHABETA];
//以该节点结尾是否为单词
bool isWord;
};
//创建新节点,并初始化,返回该新建节点
TrieNode* createNode()
{
TrieNode* tn = new TrieNode;
for (int i = 0; i < ALPHABETA; ++i)
{
tn->children[i] = NULL;
}
tn->isWord = false;
return tn;
}
//判断树中是否存在 word 单词
bool searchTrie(TrieNode* root, string word)
{
TrieNode* curNode = root;
for (int i = 0; i < word.length(); ++i)
{
if (curNode->children[word[i] - 'a'] == NULL)
return false;
else
curNode = curNode->children[word[i] - 'a'];
}
return (curNode->isWord);
}
//插入
void insertTrie(TrieNode* root, string word)
{
TrieNode* curNode = root;
for (int i = 0; i < word.length(); ++i)
{
int index = word[i] - 'a';
if (curNode->children[index] == NULL)
{
//不存在就创建
TrieNode* temp = createNode();
curNode->children[index] = temp;
curNode = temp;
}
else
curNode = curNode->children[index];
}
curNode->isWord = true;
}
bool noneChildren(TrieNode* t)
{
for (int i = 0; i < ALPHABETA; ++i)
{
if (t->children[i] != NULL)
return false;
}
return true;
}
//删除word单词
//如果删除之后,上一层children全为NULL,那么就可以删除上一层
//因为没有指向上一层的指针,所以需要递归实现
//返回值 true 表示可以删除,即没有children,自己也不是word
bool deleteWord(TrieNode* root, string word)
{
if (root == NULL)
return false;
if (word.length())
{
int index = word[0] - 'a';
if (root->children[index] != NULL &&
deleteWord(root->children[index], word.substr(1)) &&
!root->isWord)
{
//没孩子,则返回给parent,自己是可删的
if (noneChildren(root))
{
delete root;
root = NULL;
return true;
}
else
{
return false;
}
}
}
//找到最后
else if (word.length() == 0 && root->isWord)
{
//没孩子,则返回给parent,自己是可删的
if (noneChildren(root))
{
delete root;
root = NULL;
return true;
}
//有孩子的化,就只改变isWord的状态,并返回不可删
else
{
root->isWord = false;
return false;
}
}
return false;
}
//展示所有词
void showAll(TrieNode* root, string show="")
{
if (root->isWord)
cout << show << " ";
TrieNode* cur = root;
for (int i = 0; i < ALPHABETA; ++i)
{
if (cur->children[i] != NULL)
{
showAll(cur->children[i], show + char(i + 'a'));
}
}
}
int main()
{
//构建一个基础词库
string library[6] = { "hwh","bjtu","hwhwh","vscode","visual","vs" };
TrieNode* root = createNode();
for (int i = 0; i < 6; i++)
insertTrie(root, library[i]);
while (true)
{
cout << "*******************" << endl;
cout << "1.插入" << endl;
cout << "2.查询" << endl;
cout << "3.删除" << endl;
cout << "4.显示所有" << endl;
cout << "请输入你的选择:" << endl;
int choice;
while (cin >> choice)
{
if (choice >= 1 && choice <= 4)
break;
else
cout << "请输入你的选择:" << endl;
}
string word;
switch (choice) {
case 1:
cout << "请输入待插入的单词:" << endl;
cin >> word;
insertTrie(root, word);
break;
case 2:
cout << "请输入待查询的单词:" << endl;
cin >> word;
searchTrie(root,word) ? cout << "存在\n" : cout << "不存在\n";
break;
case 3:
cout << "请输入待删除的单词:" << endl;
cin >> word;
deleteWord(root, word);
break;
case 4:
cout << "词库中存在以下单词:" << endl;
showAll(root);
cout << endl;
break;
}
}
return 0;
}