数据结构之字典树

什么是字典树

字典树是一种树形结构,利用字符串的公共前缀来减少查询时间,以空间换时间;根节点不包含字符,除根节点外每一个节点都只包含一个字符;从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。

如图是一个字典树,共有12个节点不为NULL,其中根节点不包含字符。那么这棵树中有几个单词呢?hell、hello、help、world,共四个单词。节点标记为红色表示根节点到该节点所形成的字符串存在。

 

如何实现字典树

下面以字符串查找问题为例,介绍字典树使用。
问题描述如下:
实现一个 Trie,包含 insert, search, 和 startsWith 这三个方法, 假设所有单词均由小写字母组成。
insert插入单词,search查找单词,startsWith是否包含以查询词为前缀的单词。
样例
insert(“hello”)
search(“hell”) // return false
startsWith(“hell”) // return true
startsWith(“helloworld”) // return false
insert(“helloworld”)
search(“hello) // return true
startsWith(“helloworld”) // return true

 

字符种类数目

const int MAX_CHAR = 26;

字典树节点TrieNode

child是TrieNode指针数组,指向子节点,0-25这26个下标与a-z这26个小写字母一一对应。

也就是说,一个节点表示哪个字符,是由该节点在父节点的child数组的下标所决定的。

flag标记当前字符串是否存在,true相当于在前面的图中将节点标记为红色,false则为黑色。

 

 

字典树TrieTree

只是将TrieNode实现的方法进行封装。

 

 

#include<cstdio>

#include<cstring>

#include<iostream>

#include<string>

#include<algorithm>

using namespace std;

const int MAX_CHAR=26;

class TrieNode {

    public:

        TrieNode()

        {

            flag=false;

            for(int i=0;i<MAX_CHAR; i++) {

                childs[i]=NULL;

            }

        }

        ~TrieNode()

        {

            for(int i=0;i<MAX_CHAR; i++) if(childs[i]!=NULL) {

                    delete childs[i];

                    childs[i]=NULL;

            }

           
        }

        //递归插入一个单词,每次建立其中的一个字符

        void insert(const string& word, int i)

        {

            int pos=word[i]-‘a‘;

            if(childs[pos]==NULL)

                childs[pos]=new TrieNode;

            if((int)word.length()-1==i) childs[pos]->flag=true;

            else childs[pos]->insert(word, i+1);

        }

        //递归查找一个单词,每次校验其中的一个字符

        bool search(const string& word, int i)

        {

            int pos=word[i]-‘a‘;

            //当前位置字符在当前节点的孩子对应于NULL,查找失败

            if(childs[pos]==NULL) return false;

            //若查找到了最后一个字符,当前节点的对应孩子的flag标记了该单词是否存在

            //否则递归校验

            if((int)word.length()-1==i) return childs[pos]->flag;

            else return childs[pos]->search(word, i+1);

        }

        bool startwith(const string& word, int i)

        {

            int pos=word[i]-‘a‘;

            if(childs[pos]==NULL) return false;

            //只要查找到最后一个字符前未失败说明以该单词为前缀的单词存在

            if((int)word.length()-1==i) return true;

            else return childs[pos]->startwith(word, i+1);

        }

    private:

        TrieNode* childs[MAX_CHAR];

        bool flag;

};

class TrieTree {

    public:

        TrieTree()

        {

            root=new TrieNode();

        }

        ~TrieTree()

        {

           delete root;

        }

        void insert(const string& word)

        {

            root->insert(word, 0);   
        }

        bool search(const string& word)

        {

            return root->search(word, 0);

        }

        bool startwith(const string& word)

        {

            return root->startwith(word, 0);

        }

    private:

        TrieNode* root;

};

const char* str[]

{

    "hello",

        "helloworld",

        "acm",

    "acmhello",

        "helloo",

};

const char* str2[]

{

    "acmhell",

        "helloo",

        "acmh"

};

const char* str3[]

{

    "hell",

        "heo",

        "helo",

        "xxx",

        "acm"

};

int main()

{

    TrieTree trie;

    for(int i=0;i<sizeof(str)/sizeof(str[0]); i++)

            trie.insert(str[i]);

    for(int i=0;i<sizeof(str)/sizeof(str[0]); i++)

        if(trie.search(str[i]))

            cout<<"find "<<str[i]<<endl;

        else

            cout<<"not find "<<str[i]<<endl;

    for(int i=0;i<sizeof(str2)/sizeof(str2[0]); i++)

        if(trie.search(str2[i]))

            cout<<"find "<<str2[i]<<endl;

        else

            cout<<"not find "<<str2[i]<<endl;

    for(int i=0;i<sizeof(str3)/sizeof(str3[0]); i++)

        if(trie.startwith(str3[i]))

            cout<<"startwith "<<str3[i]<<endl;

        else

            cout<<"not startwith "<<str3[i]<<endl;

    return 0;

}

时间: 2024-10-13 05:43:17

数据结构之字典树的相关文章

[从头学数学] 第255节 Python实现数据结构:字典树(Trie)

剧情提要: 阿伟看到了一本比较有趣的书,是关于<计算几何>的,2008年由北清派出版.很好奇 它里面讲了些什么,就来看看啦. 正剧开始: 星历2016年08月03日 09:35:13, 银河系厄尔斯星球中华帝国江南行省. [工程师阿伟]正在和[机器小伟]一起研究[计算几何]]. 关于字典树的实现,已经有非常多的博文涉及到了.但基本都是用内嵌数组/列表实现的. 本博文是它的递归实现. <span style="font-size:18px;">### # @usa

【数据结构】字典树/Trie树/前缀树 - 字符串的统计、排序和保存

字典树 描述 字典树,又称单词查找树.Trie树.前缀树,是一种树形结构,是一种哈希树的变种. 典型应用是用于统计.排序和保存大量的字符串(但不仅限于字符串). 常见操作有插入和查找,删除操作少见. 性质 根节点不包含字符 除根节点外每一个节点都只包含一个字符 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串 每个节点的所有子节点包含的字符都不相同 优点 利用字符串的公共前缀来减少查询时间 最大限度地减少无谓的字符串比较 查询效率比哈希树高 自带字典序排序 直接判断重复,或者记

nyoj 290 动物统计加强版 (字典树 PS:map&lt;TLE&gt;)

动物统计加强版 时间限制:3000 ms  |  内存限制:150000 KB 难度:4 描述 在美丽大兴安岭原始森林中存在数量繁多的物种,在勘察员带来的各种动物资料中有未统计数量的原始动物的名单.科学家想判断这片森林中哪种动物的数量最多,但是由于数据太过庞大,科学家终于忍受不了,想请聪明如你的ACMer来帮忙. 输入 第一行输入动物名字的数量N(1<= N <= 4000000),接下来的N行输入N个字符串表示动物的名字(字符串的长度不超过10,字符串全为小写字母,并且只有一组测试数据).

白话算法与数据结构之【字典树】

1. 什么是trie树 1.Trie树 (特例结构树) Trie树,又称单词查找树.字典树,是一种树形结构,是一种哈希树的变种,是一种用于快速检索的多叉树结构.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高.      Trie的核心思想是空间换时间.利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的. Trie树也有它的缺点,Trie树的内存消耗非常大.当然,或许用左儿子

9-11-Trie树/字典树/前缀树-查找-第9章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第9章  查找 - Trie树/字典树/前缀树(键树) ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.Scanf.c        相关测试数据

【数据结构】前缀树/字典树/Trie

[前缀树] 用来保存一个映射(通常情况下 key 为字符串  value 为字符串所代表的信息) 例如:一个单词集合 words = {  apple, cat,  water  }   其中 key 为单词      value 代表该单词是否存在 words[ 'apple' ] = 存在     而     word[ ' abc' ] = 不存在 图示:一个保存了8个键的trie结构,"A", "to", "tea", "ted

【学习总结】数据结构-Trie/前缀树/字典树-及其最常见的操作

Trie/前缀树/字典树 Trie (发音为 "try") 或前缀树是一种树数据结构,用于检索字符串数据集中的键. 一种树形结构,是一种哈希树的变种. 典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计. 优点:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高. 应用: 自动补全 END 原文地址:https://www.cnblogs.com/anliux/p/12590368.html

C++实现字典树数据结构_LeetCode820_字典的压缩编码

用C++实现字典树数据结构的例子: 例题: 单词的压缩编码 给定一个单词列表,我们将这个列表编码成一个索引字符串 S 与一个索引列表 A. 例如,如果这个列表是 ["time", "me", "bell"],我们就可以将其表示为 S = "time#bell#" 和 indexes = [0, 2, 5]. 对于每一个索引,我们可以通过从字符串 S 中索引的位置开始读取字符串,直到 "#" 结束,来恢复我们

字典树 一种快速插入查询数据结构

定义 字典树,又称单词查找树,Trie树,是一种树形结构,典型应用是用于统计,排序和保存大量的字符串,所以经常被搜索引擎系统用于文本词频统计.它的优点是:利用字符串的公共前缀来节约存储空间,最大限度的减少无谓的字符串比较,查询效率比哈希表高. 解释 这个图片比较经典 就是在每一次边存的是字符,点标记着个点是否之前的边的字符都存在 如图存在的字符串有 abc abcd abd.... 代码 #include <cstdio> #include <cstring> #include &