来着wiki百科的介绍
trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。
trie树的查询速度,小于串长,所以速度很快,但空间代价很高(26^max(len))。与hash类似的情况。
主要用于快速查询,词频统计,前缀匹配,字符串排序(先序遍历,遇到为字符串输出)。
代码如下:
#include "vld.h"
#include <iostream>
#include <cassert>
#include <cctype>
using namespace std;
//申明使用必须为小写字母,否则出错!!
const int MAX_CHAR = 26;
typedef struct node
{
int prefix_count;
bool is_str;
node *next[MAX_CHAR];
node()
{
is_str = false;
memset(next,NULL,sizeof(node*)*MAX_CHAR);
}
}Trie;
void insert(node *root ,char* str)
{
assert(root);
node *p = root;
for (int i = 0;str[i];i++)
{
assert(isalpha(str[i]));
int index = tolower(str[i]) - 'a';
if (p->next[index] == NULL)
{
p->next[index] = new node;
}
p->prefix_count ++;
p = p->next[index];
}
p->is_str = true;
}
bool find(node *root ,char* str)//基本和插入类似都得遍历一边
{
assert(root);
node *p = root;
for (int i = 0;str[i];i++)
{
assert(isalpha(str[i]));
int index = tolower(str[i]) - 'a';
if (p->next[index] == NULL)
{
return false;//此处!!
}
p = p->next[index];
}
return p->is_str;//防止是中间的的前缀,而非完整的字符串(也可以直接返回真,表明找到前缀)
}
void delete_trie(node *root)
{
for (int i = 0;i < MAX_CHAR;i++)//总共一个才删!!
{
if (root->next[i] != NULL)
{
delete_trie(root->next[i]);//回溯的方法删除!!
}
}
delete root; //技巧性很强!删除!!
}
int main()//必须保证只有字母!!
{
char str[21];
char ch;
Trie *root = new Trie;
do
{
cout<<"输入字符串(20内):"<<endl;
cin>>str;
insert(root,str);
cout<<"继续?Y/N"<<endl;
cin.get();//去换行
cin.get(ch);
}while(ch != 'N'&&ch != 'n');
cout<<"查找测试!"<<endl;
do
{
cout<<"输入字符串(20内):"<<endl;
cin>>str;
if(find(root,str))
{
cout<<"找到!"<<endl;
}
else
{
cout<<"未找到!"<<endl;
}
cout<<"继续?Y/N"<<endl;
cin.get();//去换行
cin.get(ch);
}while(ch != 'N'&&ch != 'n');
delete_trie(root);
return 1;
}
//注要注意:对trie树的释放,并较好的的利用递归树。