//这是ZLH.的第一篇博客,喜欢就给个赞吧!
By ZLH.
字典树::介绍
字典树是一种用于存储字符串的数据结构。
字典树是一种多叉树(废话)。
字典树的每一个节点都有26(字典量)个子节点。
如下图,从根节点出发的每一条路径都是一个单词,带星号的地方是单词结尾。
Root
-> A -> B -> S -> E -> N -> T*
-> C -> C -> E -> P -> T*
-> P -> P -> L -> E*
-> B -> E -> C -> O -> M -> E*
-> G -> I -> N*
-> C -> A -> T* 好像并不够形象诶(逃
一般字典树的根节点会空出来,并不储存信息。
字典树::声明
字典树支持的操作有:
- 插入字符串,存值。
- 查找字符串,并返回它的值。
接下来将会逐一实现。
字典树::实现
还是用我常用的结构体封装法写代码吧。
#include<bits/stdc++.h>
using namespace std;
struct Trie{
Trie(){
}
void add(string s,int val){
}
int query(string s){
}
};
我们先要记录每个节点的26个孩子,并记录这个节点的值及它是否单词结尾。
idx为字符映射
struct Trie{
static const int MAXN=10000+10;
static const int MAXW=26;
int son[MAXN][MAXW];
int data[MAXN];
bool is_word[MAXN];
int top; //节点数
Trie(){
memset(son,0,sizeof(son));
memset(is_word,0,sizeof(is_word));
top=0;
}
int idx(char c){ //字符映射
return c-'a';
}
void add(string s,int val){
}
int query(string s){
}
};
开始插入
void add(string s,int val){
}
假设现在有一棵字典树,现有单词ABS和B。
现在要插入单词 "BGM"。
我们先从根节点0号开始,遍历字符串s。
int u=0; //现在节点
s[0]为 'B',我们顺着树上的 'B' 边走。
char ch=idx(s[i]);
u=son[u][ch]; //移动
s[1]为 'G',在遍历树的过程中发现并不存在 'G' 节点,我们选择新增一个节点。
链接 'B' 到 'G' ,并移动到点 'G'。
char ch=idx(s[i]);
if(!son[u][ch]){
top++;
son[u][ch]=top;
}
u=son[u][ch];
同理得到最后一个节点 'M'。
得到单词 "BGM" 后就可以在最后一个单词 'M' 上存入数据了。
记得将is_word设为1。
data[u]=val;
is_word[u]=true;
完整代码:
void add(string s,int val){
int u=0;
for(int i=0;i<s.size();i++){
char ch=idx(s[i]);
if(!son[u][ch])
son[u][ch]=++top;
u=son[u][ch];
}
data[u]=val;
is_word[u]=true;
}
查询
查询操作与插入类似。
查询操作通过遍历字符串来得到最终字符串尾。
若遍历时发现边不存在,返回找不到。
若串尾is_word为真,返回数据,否则返回找不到。
完整代码:
int query(string s){
int u=0;
for(int i=0;i<s.size();i++){
char ch=idx(s[i]);
if(!son[u][ch])
return -1; //找不到
u=son[u][ch];
}
if(is_word[u])
return data[u];
else
return -1;
}
字典树完整代码:
#include<bits/stdc++.h>
using namespace std;
struct Trie{
static const int MAXN=10000+10;
static const int MAXW=26;
int son[MAXN][MAXW];
int data[MAXN];
bool is_word[MAXN];
int top; //节点数
Trie(){
memset(son,0,sizeof(son));
memset(is_word,0,sizeof(is_word));
top=0;
}
int idx(char c){ //字符映射
return c-'a';
}
void add(string s,int val){
int u=0;
for(int i=0;i<s.size();i++){
char ch=idx(s[i]);
if(!son[u][ch])
son[u][ch]=++top; //新增节点
u=son[u][ch];
}
data[u]=val;
is_word[u]=true;
}
int query(string s){
int u=0;
for(int i=0;i<s.size();i++){
char ch=idx(s[i]);
if(!son[u][ch])
return -1; //找不到
u=son[u][ch];
}
if(is_word[u])
return data[u];
else
return -1;
}
};
有什么疑问或提议请从犇犇留言哦!^_^
于 19:10 完成。