码迷,mamicode.com
首页 > 其他好文 > 详细

【数据结构】Trie树

时间:2015-05-11 09:05:50      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:

      Trie树,即字典树,是一种树形结构,最大限度地减少无谓的字符串比较;典型应用是用于统计和排序大量的字符串(但不仅限于字符串);
    

基本知识

(1)Trie的核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的;

(2)根节点不包含字符,除根节点外每一个节点都只包含一个字符,节点保存对应的字符值;

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

(4)每个节点的所有子节点包含的字符都不相同;

(5)由于某些单词是其他单词的前缀,因此每一个节点增加是否为单词的标识


基本实现

struct TrieNode
{
  char value;
  vector<TrieNode*> children;
  bool word;
};

class Trie
{
public:
  Trie()
  {
    root = new TrieNode();
    root->word = false;
  }

  ~Trie()
  {
    _deleteTrieNode(root);
  }

  void insert(string s)
  {
    TrieNode* node = root;
    for (int i=0; i < s.size(); ++i)
      {
        if (!isalpha(s[i]))
          return;

        vector<TrieNode*>& children = node->children;
        if (children.empty())
          children.assign(26, NULL);

        int index = tolower(s[i]) - 'a';
        if (children[index])
          {
            node = children[index];

            if (i == s.size()-1)
              node->word = true;
          }
        else
          {
            TrieNode* child = new TrieNode();
            child->value = s[i];

            if (i < s.size()-1)
              {
                child->word = false;
              }
            else
              {
                child->word = true;
              }

            children[index] = child;

            node = child;
          }
      }
  }

  bool search(string key)
  {
    TrieNode* node = root;
    int i = 0;
    bool flag = false;
    for (i=0; i < key.size(); ++i)
      {
        if (!isalpha(key[i]))
          return false;

        vector<TrieNode*>& children = node->children;
        if (children.empty())
          return false;

        int index = tolower(key[i]) - 'a';

        TrieNode* child = children[index];
        if (child)
          {
            node = child;
            flag = child->word;
          }
        else
          {
            return false;
          }
      }

    return flag;
  }

  bool startsWith(string prefix)
  {
    TrieNode* node = root;
    for (int i=0; i < prefix.size(); ++i)
      {
        if (!isalpha(prefix[i]))
          return false;

        vector<TrieNode*>& children = node->children;
        if (children.empty())
          return false;

        int index = tolower(prefix[i]) - 'a';
        TrieNode* child = children[index];
        if (child)
          {
            node = child;
          }
        else
          {
            return false;
          }
      }

    return true;
  }

private:
  void _deleteTrieNode(TrieNode* node)
  {
    for (int i=0; node && i < node->children.size(); ++i)
      _deleteTrieNode(node->children[i]);

    if (node)
      delete node;
  }

  TrieNode* root;
};

说明几点

(1)本程序的Trie树的建立,仅仅建立对应的小写字符的字典树,对于大写字符将转换为小写字符;遇到非单词字符将会提前返回;

(2)在TrieNode中word标识该节点是否为一个单词;

(3)在析构函数中,利用递归来释放每一个节点的内存;


基本应用

描述:给你100000个长度不超过10的单词。对于每一个单词,我们要判断他出没出现过,如果出现了,求第一次出现在第几个位置。

解决办法:

(1)由于单词长度不超过10,建立Trie树也是可以忍受的,空间的花费不会超过(单词数*单词长度)个TrieNode;还且可以在边查询时边建立Trie树;

(2)若单词第一次出现,查询时建立Trie树,在最后一个节点标识该单词第一次出现的位置,可以修改TrieNode的word标识类型为int(默认值为-1),存放第一次出现的位置;

(3)若单词不是第一次出现,那么在查询到该单词最后一个字符时,该字符的word标识不为-1,说明已经该单词已经出现,word的值为该单词第一次出现的位置;

【数据结构】Trie树

标签:

原文地址:http://blog.csdn.net/skyuppour/article/details/45623917

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!