现在的位置: 首页 > 综合 > 正文

Trie树 字典树

2012年11月19日 ⁄ 综合 ⁄ 共 2290字 ⁄ 字号 评论关闭

字典树,又称单词查找树,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;
}

 

 

抱歉!评论已关闭.