栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

经典前缀树(字典树)的实现c++

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

经典前缀树(字典树)的实现c++

关于前缀树的内容最好看看视频了解逻辑结构,然后代码实现一下

前缀树是一种树形数据结构,广泛用于字符串查找,思想上类似哈希。在字符串查找上有非常好的效果,但是消耗空间较大,下面给出前缀树的c++实现

#ifndef TRIE_H_INCLUDED
#define TRIE_H_INCLUDED

#include
using namespace std;

//假设字符串都是小写字母

typedef struct TrieNode
    {   int pass = 0;     //有几个字符串经过此结点(前缀包含这个字符的字符串数量)

        int end = 0;      //以此结点结束的字符串的数量,如果不允许重复插入,可以改成bool

        TrieNode* next[26]{nullptr};     //26个空位,准备挂下一结点a-z ,没有时置为nullptr

    }TrieNode ;     //前缀树结点定义



//前缀树
class Trie {
public:

    TrieNode *root = nullptr;   //根节点



    Trie() {
        root = new TrieNode();    //构造函数初始化root
    }

    ~Trie() {
        deletememory(root);      //析构释放空间
    }


    
    void insert(string word) {

        TrieNode *temp = root;
        temp->pass++;        
        //根节点的pass代表树上有多少字符串以空字符串为前缀,也就是字符串总数

        for(unsigned int i = 0 ;inext[word[i]-'a'] == nullptr)   //如果先前没有字符串经过此结点
                temp->next[word[i]-'a'] = new TrieNode();    //建出新结点
            temp = temp->next[word[i]-'a'];
            temp->pass++;
        }
        temp->end++;      //temp指向字符串最后一个结点,end++表示多了一个字符串以此结点结尾
    }

    
    bool search(string word) {
        TrieNode *temp = root;
        for(char c : word)        //遍历字符串每个字符,也可以使用for i~word.size写法
        {
            if(temp->next[c-'a'] == nullptr )  //找的过程发现没路了,false
                return false;
            temp = temp->next[c-'a'];
        }
        return temp->end;
    }

    
    bool startsWith(string prefix) {
        TrieNode *temp = root;
        for(unsigned int i = 0 ;i
next[prefix[i]-'a'] == nullptr)
                return false;
            temp = temp->next[prefix[i]-'a'];
        }
        return true;
    }


    
    void deletememory( TrieNode *temp) {
        for(int i = 0 ;i < 26; i++)   //对一个结点,将其next数组存放的后续节点全部释放
            if(temp->next[i])
               deletememory(temp->next[i]);
        delete temp;    //释放本结点空间
    }


    
    void remove(string word) {
        if(true == search(word))   //树上有这个字符串才需要删除
        {
            TrieNode *temp = root;
            temp->pass--;
            for(unsigned int i = 0 ; i< word.size() ;i++)
            {
                if( --temp->next[word[i]-'a']->pass  == 0)   //唯一经过该结点的字符串被删除
                {
                    deletememory(temp->next[word[i]-'a'] );  //递归释放此结点后面路径
                    temp->next[word[i]-'a'] = nullptr;   结点置nulptr
                    return ;
                }
                temp = temp->next[word[i] - 'a'];
            }
            temp->end--;     //如果字符串所有字符删除后,路径没变,还需要把最后结点end-1
        }
    }

};
#endif // TRIE_H_INCLUDED

上面所给出的实现要求字符串都是小写字母,但如果字符种类非常多,我们需要将存储下一结点的数据结构进行修改,因为定长数组的方式可能会造成空间巨大的浪费,我们可以使用哈希map的方式存储 <字符,下一结点>

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1030707.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号