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

      如果以树的多重链表表示键树,则树的每个结点中应包含d个(d为关键字符的基,如:字符集由英文大写字母构成时,则d=26)指针域,此时的键树又称为Trie树。

    关于Trie树的思想和优点:
      1、Trie树利用字符串的公共前缀来降低时空开销
      2、Trie树的典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计
      3、Trie树的优点是最大限度地减少无谓的字符串比较。
      4、Trie树的缺点是如果存在大量字符串且这些字符串基本没有公共前缀,则相应的Trie树将非常消耗内存。
    const int branchNum = 26;  //26个英文字母
    class Trie_node
    {
    public:
            Trie_node():isStr(false){ memset(next,NULL,sizeof(next)); } 
    //初始结点是否到达一个字符串标记为false,指向各个结点的指针都为NULL
    public:
            bool isStr;  //记录此处是否构成一个串
            Trie_node* next[branchNum];  //指向各个子树的指针,数组下标就相当于字母的值
    };



    如右图所示,每个结点包含一个isStr和一个next数组,如果isStr==true,就表示从_root结点到该结点之间的路径对应的数组下标就是一个存在的字符串,右图中 aa是一个存在的字符串

    #include<iostream>
    #include<string.h>
    using namespace std;
    const int branchNum = 26;  //26个英文字符

    class Trie_node
    {
    public:
            Trie_node():isStr(false){ memset(next,NULL,sizeof(next)); }  
    public:
            bool isStr;  
            Trie_node* next[branchNum]; 
    };

    class Trie
    {
    public:
            Trie():_root(new Trie_node())  {}
            void insert(const char* word);
            bool search(const char* word)const;
            void deleteTrie(Trie_node* root);
            Trie_node* getTrie()const{ return _root; }
    private:
            Trie_node* _root;
    };

    //main文件测试
    int main()
    {
            Trie myTrie;
            const char* arr[] = {"mei","hao","hello","world"};
            for(int idx=0;idx!=4;++idx)
            {
                    myTrie.insert(arr[idx]);
            }
            cout<<endl;
            for(int idx=0;idx!=4;++idx)
            {
                    cout<<myTrie.search(arr[idx])<<" ";
            }
            cout<<endl;
            cout<<myTrie.search("meihao")<<endl;
            system("pause");
    }


    //类实现文件
    void Trie::insert(const char* word)
    {
            Trie_node* cur = getTrie();
            while(*word)
            {
                    if(cur->next[*word - 'a']==NULL)
                    {
                            Trie_node* node = new Trie_node();
                            cur->next[*word - 'a'] = node;
                    }
                    cur = cur->next[*word - 'a'];  //指向下一个
                    ++word;
            }
            //插入完毕,字符串最后一个结点标记为true,表示到此已经是一个单词了
            cur->isStr = true;
    }

    bool Trie::search(const char* word)const
    {
            Trie_node* cur = getTrie();
            while(*word&&NULL!=cur)  //单词还没匹配完,下一个字符存在,就接着向下匹配
            {
                    cur = cur->next[*word - 'a'];
                    ++word;
            }
            //判断是不是找到了这个字符串
            return (cur!=NULL && cur->isStr);  //注意这里的判断顺序,如果第一个满足,接着判断第二个;如果第一个不满足就直接返回;是一个开关语句
            // 如果cur==NULL,先判断cur->isStr就要段错误
    }

    void Trie::deleteTrie(Trie_node* root)
    {
            if(NULL!=root)
            {
                    for(int idx=0;idx!=branchNum;++idx)
                    {
                            deleteTrie(root->next[idx]);
                            delete root;
                            root = NULL;
                    }
            }
    }



  • 相关阅读:
    poj2452
    bnuoj16491
    1326: The contest(并查集+分组背包)
    BNUOJ-1065或运算的简单解法
    递推、规律思维题总结
    uva10160(dfs+状态压缩)
    第七章 人工智能,7.1 基于深度强化学习与自适应在线学习的搜索和推荐算法研究(作者:灵培、霹雳、哲予)
    第六章 大数据,6.3 突破传统,4k大屏的沉浸式体验(作者: 彦川、小丛)
    第六章 大数据,6.2 双11背后的大规模数据处理(作者:惠岸 朋春 谦乐)
    第六章 大数据,6.1 双11数据大屏背后的实时计算处理(作者:藏六 黄晓锋 同杰)
  • 原文地址:https://www.cnblogs.com/meihao1203/p/9508810.html
Copyright © 2011-2022 走看看