1. 程式人生 > >2018 - 6 -18 總結:字典樹

2018 - 6 -18 總結:字典樹

//這是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*       好像並不夠形象誒(逃

一般字典樹的根節點會空出來,並不儲存資訊。

字典樹::宣告

字典樹支援的操作有:

  1. 插入字串,存值。
  2. 查詢字串,並返回它的值。

接下來將會逐一實現。

字典樹::實現

還是用我常用的結構體封裝法寫程式碼吧。

#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 完成