Trie树

目录

一、概述

二、节点设计

三、插入字符串

 四、判断前缀

五、删除字符串


一、概述

Trie树,即字典树,又称前缀树单词查找树键树

Trie树的典型应用是保存大量的字符串但不限于字符串),并快速排序统计查找字符串前缀

Trie树中的根节点表示空字符串结点表示字符串前缀字符串表示字符

二、节点设计
struct Node1{//方式一
    int c;
    int p[26];//数组范围取决于题意
}trie[N];

struct Node2{//方式二
    int c;
    map<char,int>p;
}trie[N];

方式一速度快,但是空间浪费大,适合组成字符串的不同字符数量较少的情况;方式二适应范围更广,但是索引速度慢,适合组成字符串的不同字符数量较多的情况。

三、插入字符串

Trie树中初始拥有一个根节点(trie[1]),表示空串,体现在代码中是“int cnt=1;”。

插入字符串时,从根节点开始,按串中字符逐一匹配Trie树中的边,转移结点,如果当前节点没有对应字符边可匹配,则当前结点以该字符边连接新结点,再转移;如果按串中字符转移完毕,当前结点c值加1

struct Node{
    int c;
    map<char,int>p;
}trie[N];
int cnt=1;
int insert(char *s){
    int i=0,u=1;
    while(s[i]){
        if(trie[u].p.count(s[i])){
            u=trie[u].p[s[i++]];
        }
        else{
            u=trie[u].p[s[i++]]=++cnt;
        }
    }
    return ++trie[u].c;
}
 四、判断前缀

在当前Trie树中判断是否有字符串s为前缀的字符串,只需要在Trie树中转移s,如果能够将s中的字符逐一转移完毕,则说明Trie树中一定存在字符串是以s为前缀的。

bool isPrefix(char *s){
    int i=0,u=1;
    while(s[i]){
        if(trie[u].p.count(s[i])){
            u=trie[u].p[s[i++]];
        }
        else{
            return 0;
        }
    }
    return 1;
}
五、删除字符串

删除字符串有多种情况

  1. 待删除字符串为叶子结点,该串在Trie树中不止一个,直接将c值减1即可。
  2. 待删除字符串为叶子结点,该串在Trie树中只有一个,需要回溯并删除结点和边,直至其祖先结点c值不为0还有其他子节点
  3. 待删除字符串为叶子结点且唯一,但是该串在Trie树中和其他串有公共前缀,需要回溯并删除结点和边,直至其祖先结点c值不为0还有其他子节点
  4. 待删除字符串不是叶子结点,直接将c值减1即可。
bool del(char *s,int u){
    char c=s[0];
    if(!c){
        if(trie[u].c){
            trie[u].c--;
        }
        else{
            return 0;
        }
    }
    else if(trie[u].p.count(c)){
        if(del(s+1,trie[u].p[c])){
            trie[u].p.erase(c);
        }
        else{
            return 0;
        }
    }
    else{
        return 0;
    }
    if(!trie[u].c&&!trie[u].p.size()){
        return 1;
    }
    else{
        return 0;
    }
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值