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

    特性

    Trie树属于树形结构,查询效率比红黑树和哈希表都要快。假设有这么一种应用场景:有若干个英文单词,需要快速查找某个单词是否存在于字典中。使用Trie时先从根节点开始查找,直至匹配到给出字符串的最后一个节点。在建立字典树结构时,预先把带有相同前缀的单词合并在同一节点,直至两个单词的某一个字母不同,则再从发生差异的节点中分叉一个子节点。

    节点结构:
    每个节点对应一个最大可储存字符数组。假设字典只存26个小写英文字母,那么每个节点下应该有一个长度为26的数组。换言说,可存的元素类型越多,单个节点占用内存越大。如果用字典树储存汉字,那么每个节点必须为数千个常用汉字开辟一个数组作为储存空间,占用的内存实在不是一个数量级。不过Trie树就是一种用空间换时间的数据结构,鱼和熊掌往往不可兼得。

    建树细节:

    • 取要插入字符串的首个字符,从根节点的孩子节点开始,匹配当前字符是否已有节点,有则把指针指向该节点。无则为该字符创建节点,并把指针指向该新建节点。
    • 迭代。
    • 遇到要插入字符串末尾结束符时停止迭代,并把最后一个非’′字符对应的节点设为末端节点。

    查找细节:
    循环取要插入字符串的首个字符,从根节点的孩子节点开始,匹配当前字符是否已有节点,有则继续循环,无则返回False. 直至匹配到最后一个字符则完成查找。

    树结构图:
    我们用apps, apply, apple, append, back, basic, backen几英文单词创建树形结构:
    trie

    上图很容易看出,有相同前缀的英文单词,会合并在同一个节点,Trie树顺着一个个节点进行检索,直至找到最后一个节点。代码如下:

     1 #include <stdio.h>
     2  
     3 struct trie_node
     4 {
     5     static const int letter_count = 26;
     6  
     7     int count;
     8     bool is_terminal;
     9     char letter;
    10     trie_node* childs[letter_count];
    11  
    12     trie_node()
    13         : letter(0), count(1), is_terminal(false)
    14     {
    15         for (int i = 0; i < letter_count; ++i)
    16             childs[i] = NULL;
    17     }
    18 };
    19  
    20 class trie
    21 {
    22 public:
    23     trie()
    24         : root_node_(NULL)
    25     {
    26     }
    27  
    28     ~trie()
    29     {
    30         delete_trie(root_node_);
    31     }
    32  
    33 public:
    34     trie_node* create()
    35     {
    36         trie_node* n = new trie_node();
    37         return n;
    38     }
    39  
    40     void insert(const char* str)
    41     {
    42         if (!root_node_ || !str)
    43             root_node_ = create();
    44  
    45         trie_node* next_element_node = root_node_;
    46         while (*str != 0)
    47         {
    48             char element_index = *str - 'a';
    49             if (!next_element_node->childs[element_index])
    50             {
    51                 next_element_node->childs[element_index] = create();
    52             }
    53             else
    54             {
    55                 next_element_node->childs[element_index]->count++;
    56             }
    57  
    58             next_element_node = next_element_node->childs[element_index];
    59             next_element_node->letter = *str;
    60             str++;
    61         }
    62  
    63         next_element_node->is_terminal = true;
    64     }
    65  
    66     bool find_word_exists(const char* str)
    67     {
    68         if (!root_node_ || !str)
    69             return NULL;
    70  
    71         trie_node* element_node = root_node_;
    72         do
    73         {
    74             element_node = element_node->childs[*str - 'a'];
    75             if (!element_node) return false;
    76             str++;
    77         } while (*str != 0);
    78  
    79         return element_node->is_terminal;
    80     }
    81  
    82     void delete_trie(trie_node* node)
    83     {
    84         if (!node) return;
    85         for(int i = 0; i < trie_node::letter_count; i++)
    86         {
    87             if(node->childs[i] != NULL)
    88                 delete_trie(node->childs[i]);
    89         }
    90  
    91         delete node;
    92     }
    93  
    94 private:
    95     trie_node* root_node_;
    96 };

    转:http://powman.org/archives/trie.html

  • 相关阅读:
    分布式框架---Dubbox 简介
    MySql 多表查询
    MySql 增删改查
    redis
    spring security 自定义登录页面及从数据库查询账户登录
    java数据结构-
    Maven-
    有关多行相同数据,只显示在第一行的实现
    javaWEB的第一次MVC之旅
    JavaWeb中的 请求转发 和 重定向
  • 原文地址:https://www.cnblogs.com/churi/p/3928359.html
Copyright © 2011-2022 走看看