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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值