2018 - 6 -18 總結:字典樹
阿新 • • 發佈:2018-11-16
//這是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 完成。