C++自定义字典树结构

20 篇文章 0 订阅
19 篇文章 0 订阅
代码 
#include <iostream>
using namespace std;

class TrieNode
{
public:
    char data;
    TrieNode* children[26];
    bool isTerminal;

    TrieNode(char ch)
    {
        data = ch;
        for (int i = 0; i < 26; i++)
        {
            children[i] = NULL;
        }
        isTerminal = false;
    }
};
class Trie
{
public:
    TrieNode* root;
    Trie()
    {
        root = new TrieNode('\0');
    }
    void insertUtil(TrieNode* root, string word)
    {
        // base case
        if (word.length() == 0)
        {
            root->isTerminal = true;
            return;
        }
        // assumption , world will be CAPS
        int index = word[0] - 'A';
        TrieNode* child;
        // present
        if (root->children[index] != NULL)
        {
            child = root->children[index];
        }
        else
        {
            // absent
            child = new TrieNode(word[0]);
            root->children[index] = child;
        }
        // RECURSION
        insertUtil(child, word.substr(1));
    }
    void insertWord(string word)
    {
        insertUtil(root, word);
    }
    bool searchUtil(TrieNode* root, string word)
    {
        // base case
        if (word.length() == 0)
        {
            return root->isTerminal;
        }
        int index = word[0] - 'A';
        TrieNode* child;
        // present
        if (root->children[index] != NULL)
        {
            child = root->children[index];
        }
        else
        {
            // absent
            return false;
        }
        // RECURSION
        return searchUtil(child, word.substr(1));
    }
    bool searchWord(string word)
    {
        return searchUtil(root, word);
    }
};


#include <bitset>
#include <unordered_map>
#include <vector>
template <std::size_t N>
using Signature = std::bitset<N>;

// util function to split string into parts by given delimiter.
static void split(std::string_view s, std::vector<std::string>& parts, char delimiter) {
    parts.emplace_back();
    for (auto ch : s) ch == delimiter ? parts.push_back("") : parts.back().push_back(ch);
};

// A MyTrie structures ids by names into a tree.
template <std::size_t N>
class MyTrie {
private:
    // Signature of all signals under this tree.
    // e.g. the node `b` matches all "a.b.*"
    Signature<N> signature;
    // Child tries.
    std::unordered_map<std::string, MyTrie*> children;
    // If it's a end node of a signal's name, the signal id of which.
    size_t id = 0;
    char m_delimiter;

public:
    MyTrie(char delimiter = '.') : m_delimiter(delimiter){}
    ~MyTrie() {  // free every child recursively
        for (auto p : children) delete p.second;
    }
    // Puts a signal id onto this tree by signal name.
    void Put(std::string_view name, size_t id) {
        std::vector<std::string> parts;
        split(name, parts, m_delimiter);
        auto t = this;  // t is the node walked through
        for (const auto& p : parts) {
            // Creates a node if not exist.
            if (auto [it, inserted] = t->children.try_emplace(p, nullptr); inserted) it->second = new MyTrie();
            // Mark this signal id to its signature.
            t->signature[id] = 1;
            t = t->children[p];
        }
        // The last node.
        t->id = id;
    }
    // Match signals by given pattern, returns a signature of matched signal ids.
    Signature<N> Match(std::string_view pattern) const {
        Signature<N> sig;
        std::vector<std::string> parts;
        split(pattern, parts, m_delimiter);
        auto t = this;
        for (const auto& p : parts) {
            // matches all under the subtree
            if (p == "*")
                return t->signature;
            else {  // match by exact name
                // match failure, returns empty signature
                if (t->children.find(p) == t->children.end()) return sig;
                t = t->children.at(p);
            }
        }
        // The last node, matches a single signal.
        sig[t->id] = 1;
        return sig;
    }
};

int test()
{
    // 基础添加查找,单个字符为一组,进行字符串词典构建
    Trie* t = new Trie();

    t->insertWord("ARM");
    t->insertWord("DO");
    t->insertWord("TIME");
    cout << "Present or Not " << t->searchWord("TIM") << endl;  // Present or Not 0
    cout << "Present or Not " << t->searchWord("TIME") << endl; // Present or Not 1
    
    // 扩展模式匹配,单个字符串为一组,进行字符串词典构建
    MyTrie<1024> trie;
    trie.Put("ab.cd.ef", 1);
    trie.Put("ab.cd.kk", 2);
    trie.Put("ab.xy.zz", 3);
    trie.Put("tt.xx", 4);
    trie.Put("ab.cd", 5);

    auto m1 = trie.Match("ab.cd.ef");   // m1.count() == 1
    auto m2 = trie.Match("ab.cd.*");   // m2.count() == 2

    // 字体查找
    MyTrie<1024> fontlist(' ');
    std::vector<std::string> familys = {"Noto Sans SC", "Noto Sans ", "Noto Sans Regular", "Noto Sans Bold", "Noto Sans Italic"};
    int i = 0;
    for (const auto& family : familys) {
        fontlist.Put(family, i++);
    }
    auto findList = fontlist.Match("Noto Sans *");
    for (int i = 0; i < familys.size(); i++) {
        if (findList[i]) {
            std::cout << familys[i] << std::endl;
        }
    }
    return 0;
}
输出

Present or Not 0
Present or Not 1
Noto Sans SC
Noto Sans
Noto Sans Regular
Noto Sans Bold
Noto Sans Italic


创作不易,小小的支持一下吧!

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码力码力我爱你

创作不易,小小的支持一下吧!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值