zoukankan      html  css  js  c++  java
  • Trie树 字典树

    字典树,又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。

    典型应用是用于统计、排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。

    优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。

    根节点不包含字符,除根节点外每一个节点都只包含一个字符, 每个节点的所有子节点包含的字符都不相同。

    从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。

    利用字典树查找字符串的过程,是从根节点开始,在根结点的子节点中寻找字符串的第一个字符,若找到节点,则从此节点开始进行字符串第二个字符的查找,这是一个反复、字符串逐个字符对应字典树逐层节点的查找过程。

    一个简单的实现:

    #include <iostream>
    using namespace std;
    
    
    class Trie {
    public:
        Trie();
        ~Trie();
        int32_t Insert(const char *word);
        int32_t Remove(const char *word);
        uint32_t Search(const char *word) const;
    
    private:
        static const uint32_t NUM_CHAR = 26;
        typedef struct TrieNode {
            char val;
            struct TrieNode *branch[NUM_CHAR];
            uint32_t count;
        } trie_node_t;
        trie_node_t *root;
        trie_node_t *create_node();
    
        void free(trie_node_t *node);
    
        char tolower(char c) const;
    };
    
    
    Trie::Trie(): root(NULL) {
        root = create_node();
    }
    
    
    Trie::~Trie() {
        free(root);
    }
    
    
    int32_t Trie::Insert(const char *word) {
        if (!word || strlen(word) == 0) {
            return -1;
        }
        trie_node_t *cur = root;
        const char *p = word;
        while (*p) {
            char c = tolower(*p);
            if (c == -1) {
                return -1;
            }
            uint32_t idx = c - 'a';
            if (!cur->branch[idx]) {
                cur->branch[idx] = create_node();
                cur->branch[idx]->val = c;
            }
            cur = cur->branch[idx];
            ++p;
        }
        ++cur->count;
        return 0;
    }
    
    
    int32_t Trie::Remove(const char *word) {
        if (!word || strlen(word) == 0) {
            return -1;
        }
        trie_node_t *cur = root;
        const char *p = word;
        while (*p) {
            char c = tolower(*p);
            if (c == -1) {
                return -1;
            }
            uint32_t idx = c - 'a';
            if (!cur->branch[idx]) {
                return -1;
            }
            cur = cur->branch[idx];
            ++p;
        }
        if (cur->count > 0) {
            --cur->count;
            return 0;
        }
        return -1;
    }
    
    
    uint32_t Trie::Search(const char *word) const {
        if (!word || strlen(word) == 0) {
            return 0;
        }
        trie_node_t *cur = root;
        const char *p = word;
        while (*p) {
            char c = tolower(*p);
            if (c == -1) {
                return 0;
            }
            uint32_t idx = c - 'a';
            if (!cur->branch[idx]) {
                return 0;
            }
            cur = cur->branch[idx];
            ++p;
        }
        return cur->count;
    }
    
    
    Trie::trie_node_t *Trie::create_node() {
        Trie::trie_node_t *node = new Trie::trie_node_t;
        node->val = 0;
        for (int32_t i = 0; i < Trie::NUM_CHAR; ++i) {
            node->branch[i] = NULL;
        }
        node->count = 0;
        return node;
    }
    
    
    void Trie::free(Trie::trie_node_t *node) {
        if (node) {
            for (int32_t i = 0; i < NUM_CHAR; ++i) {
                free(node->branch[i]);
            }
            delete node;
        }
    }
    
    
    char Trie::tolower(char c) const {
        if (c >= 'a' && c <= 'z') {
            return c;
        } else if (c >= 'A' && c <= 'Z') {
            return c + 32;
        }
        return -1;
    }
    
    
    int32_t main() {
        Trie trie;
        trie.Insert("haha");
        trie.Insert("haha");
        trie.Insert("hehe");
        trie.Remove("haha");
        if (trie.Search("haha") > 0) {
            cout << "find haha" << endl;
        }
        if (trie.Search("hehe") > 0) {
            cout << "find hehe" << endl;
        }
        if (trie.Search("hihi") > 0) {
            cout << "find hihi" << endl;
        }
        return 0;
    }
  • 相关阅读:
    redis的两种备份方式
    Vue—事件修饰符
    css3实现颤动的动画
    初学者可能不知道的vue技巧
    使用slot-scope复制vue中slot内容
    pre-commit钩子,代码质量检查
    爬虫可视化点选配置工具之获取鼠标点选元素
    Vue源码探究-事件系统
    使用electron实现百度网盘悬浮窗口功能!
    electron实现qq快捷登录!
  • 原文地址:https://www.cnblogs.com/caosiyang/p/2561628.html
Copyright © 2011-2022 走看看