一、简介
字典树,trie树,字母树
优点:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
树的每一条边上对应一个字符
每个顶点表示的是将根到顶点所经的边上的字符依次连接起来所对应的字符串
称Tire上的边为转移,顶点为状态
如下图样例
红色节点代表该节点为一个字符串的结尾
(白色节点就不是字符串的结尾)
从根节点到红色节点所形成的字符串,就是如图左边的字符串
很容易可以看出,Tire树很好的利用了公共前缀,节约存储空间
二、操作实现的代码
假设字符集为26个小写英文字母
(一)初始化
1、定义节点
struct node
{
bool bo; //判断该节点是否为一个字符串
//也可定义为n,用于记录该字符串数量
node *next[Z]; //存放子节点,Z为字符集大小
//可以引入map
};
2、新建节点
每次新建的节点的字符指针均应该指向空
node *Newnode()
{
node *p = new node; //新建节点
for (int i = 0; i < 26; i++)
p->next[i] = NULL; //字符指针均指向空
p->bo = false; //修改状态
return p; //返回节点指针
}
(二)插入
在插入字符串s时,令一个指针p指向根节点,然后依次遍历s中的的每一个字符c
1、当p的c字符指针指向已存在节点q,则令p=q
2、当p的c字符指针指向空,则新建一个节点q,并且令p=q
3、当字符串s遍历完毕,在当前的节点p上标记它是一个字符串的结尾
void Insert(node *p, string s)//插入一个字符串
{
for (auto x : s) //遍历字符串
{
if (p->next[x - 'a'] == NULL) //不存在,建立新节点
{
node *q = Newnode();
p->next[x - 'a'] = q;
}
p = p->next[x - 'a'];//指向下一个节点
}
p->bo = true;//遍历完毕,标记上字符串状态
}
(三)查询
在查询字符串s是否存在时,令一个指针p指向根节点,然后依次遍历s中的的每一个字符c
1、当p的c字符指针指向空时,说明s不存在,结束查询,返回false
2、当p的c字符指针指向已存在节点q,则令p=q
3、当字符串s遍历完毕,并且当前节点p被标记为一个字符串结尾,说明s存在,返回true
bool Find(node *p, string s) //查找字符串
{
for (auto x : s) //遍历该字符串
{
if (p->next[x - 'a'] == NULL) //找不到,则返回false
return false;
p = p->next[x - 'a'];
}
return p->bo; //遍历完毕,返回该节点状态
}
关于删除
tire树一般不会去删除单节点
可以用递归的方式来释放内存空间
总代码
#include <bits/stdc++.h>
using namespace std;
#define Z 30
struct node
{
bool bo; //判断该节点是否为一个字符串
//也可定义为n,用于记录该字符串数量
node *next[Z]; //存放子节点,Z为字符集大小
};
node *Newnode()
{
node *p = new node; //新建节点
for (int i = 0; i < 26; i++)
p->next[i] = NULL; //字符指针均指向空
p->bo = false; //修改状态
return p; //返回节点指针
}
void Insert(node *p, string s)
{
for (auto x : s) //遍历字符串
{
if (p->next[x - 'a'] == NULL) //不存在,建立新节点
{
node *q = Newnode();
p->next[x - 'a'] = q;
}
p = p->next[x - 'a']; //指向下一个节点
}
p->bo = true; //遍历完毕,标记上字符串状态
}
bool Find(node *p, string s) //查找字符串
{
for (auto x : s) //遍历该字符串
{
if (p->next[x - 'a'] == NULL) //找不到,则返回false
return false;
p = p->next[x - 'a'];
}
return p->bo; //遍历完毕,返回该节点状态
}
int main()
{
node *trie = Newnode(); //建立一个字典树
string s, ss;
cin >> s; //输入字符串
Insert(trie, s); //插入字符串
cin >> ss; //输入要查询的字符串
cout << (Find(trie, ss) ? "存在" : "不存在");
return 0;
}