trie树--详解

MiYu原创, 转帖请注明 : 转载自 ______________白白の屋    

 

文章作者:yx_th000 文章来源:Cherish_yimi (http://www.cnblogs.com/cherish_yimi/) 转载请注明,谢谢合作。
关键词:trie trie树 数据结构

    前几天学习了并查集和trie树,这里总结一下trie。
    本文讨论一棵最简单的trie树,基于英文26个字母组成的字符串,讨论插入字符串、判断前缀是否存在、查找字符串等基本操作;至于trie树的删除单个节点实在是少见,故在此不做详解。

l        Trie原理

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

l        Trie性质

好多人说trie的根节点不包含任何字符信息,我所习惯的trie根节点却是包含信息的,而且认为这样也方便,下面说一下它的性质 (基于本文所讨论的简单trie树)

1.    字符的种数决定每个节点的出度,即branch数组(空间换时间思想)

2.    branch数组的下标代表字符相对于a的相对位置

3.    采用标记的方法确定是否为字符串。

4.    插入、查找的复杂度均为O(len),len为字符串长度

l        Trie的示意图

如图所示,该trie树存有abc、d、da、dda四个字符串,如果是字符串会在节点的尾部进行标记。没有后续字符的branch分支指向NULL





l        
Trie
Trie的优点举例

已知n个由小写字母构成的平均长度为10的单词,判断其中是否存在某个串为另一个串的前缀子串。下面对比3种方法:

1.    最容易想到的:即从字符串集中从头往后搜,看每个字符串是否为字符串集中某个字符串的前缀,复杂度为O(n^2)。

2.    使用hash:我们用hash存下所有字符串的所有的前缀子串。建立存有子串hash的复杂度为O(n*len)。查询的复杂度为O(n)* O(1)= O(n)。

3.    使用trie:因为当查询如字符串abc是否为某个字符串的前缀时,显然以b,c,d....等不是以a开头的字符串就不用查找了。所以建立trie的复杂度为O(n*len),而建立+查询在trie中是可以同时执行的,建立的过程也就可以成为查询的过程,hash就不能实现这个功能。所以总的复杂度为O(n*len),实际查询的复杂度只是O(len)。


解释一下hash为什么不能将建立与查询同时执行,例如有串:911,911456输入,如果要同时执行建立与查询,过程就是查询911,没有,然后存入9、91、911,查询911456,没有然后存入9114、91145、911456,而程序没有记忆功能,并不知道911在输入数据中出现过。所以用hash必须先存入所有子串,然后for循环查询。

而trie树便可以,存入911后,已经记录911为出现的字符串,在存入911456的过程中就能发现而输出答案;倒过来亦可以,先存入911456,在存入911时,当指针指向最后一个1时,程序会发现这个1已经存在,说明911必定是某个字符串的前缀,该思想是我在做pku上的3630中发现的,详见本文配套的“入门练习”。

l        Trie的简单实现(插入、查询)


 1
 2#include <iostream>
 3using namespace std;
 4
 5const int branchNum = 26//声明常量 
 6int i;
 7
 8struct Trie_node
 9{
10    bool isStr; //记录此处是否构成一个串。
11    Trie_node *next[branchNum];//指向各个子树的指针,下标0-25代表26字符
12    Trie_node():isStr(false)
13    {
14        memset(next,NULL,sizeof(next));
15    }

16}
;
17
18class Trie
19{
20public:
21    Trie();
22    void insert(const char* word);
23    bool search(char* word); 
24    void deleteTrie(Trie_node *root);
25private:
26    Trie_node* root;
27}
;
28
29Trie::Trie()
30{
31    root = new Trie_node();
32}

33
34void Trie::insert(const char* word)
35{
36    Trie_node *location = root;
37    while(*word)
38    {
39        if(location->next[*word-'a'== NULL)//不存在则建立
40        {
41            Trie_node *tmp = new Trie_node();
42            location->next[*word-'a'= tmp;
43        }
    
44        location = location->next[*word-'a']; //每插入一步,相当于有一个新串经过,指针要向下移动
45        word++;
46    }

47    location->isStr = true//到达尾部,标记一个串
48}

49
50bool Trie::search(char *word)
51{
52    Trie_node *location = root;
53    while(*word && location)
54    {
55        location = location->next[*word-'a'];
56        word++;
57    }

58    return(location!=NULL && location->isStr);
59}

60
61void Trie::deleteTrie(Trie_node *root)
62{
63    for(i = 0; i < branchNum; i++)
64    {
65        if(root->next[i] != NULL)
66        {
67            deleteTrie(root->next[i]);
68        }

69    }

70    delete root;
71}

72
73void main() //简单测试
74{
75    Trie t;
76    t.insert("a");         
77    t.insert("abandon");
78    char * c = "abandoned";
79    t.insert(c);
80    t.insert("abashed");
81    if(t.search("abashed"))
82        printf("true\n");
83}

 

转载于:https://www.cnblogs.com/MiYu/archive/2010/10/23/1859515.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/380850.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

yii mysql gii_Yii Gii使用

准备数据库第1步 - 创建一个新的数据库。数据库可以通过以下两种方式进行。在终端运行 mysql -u root –p登录数据后&#xff0c;通过执行 CREATE DATABASE mystudy CHARACTER SET utf8 COLLATE utf8_general_ci; 创建一个新的数据库;第2步 - 在 config/db.php 文件中配置数据库…

通过OracleDataReader来读取BLOB类型的数据 (转载)

通过OracleDataReader来读取BLOB类型的数据 在实际的应用过程中&#xff0c;需要把大块的二进制数据存储在数据库中。读取这些大块的数据&#xff0c;可以通过强制类型转换成为byte数组&#xff0c;但是当这个二进制数据体够大时&#xff08;几十兆或者上百兆&#xff09;&…

xampp启动Apache端口被占用,修改端口

apache启动端口被占用有可能是80端口被占用&#xff0c;也用可能是443端口被占用。修改这两个端口方法如下&#xff1a; 首先打开xampp&#xff0c;点击下图的config 如果是80端口被占用&#xff0c;选择httpd,conf,会自动打开这个文件&#xff0c;然后在文件里查找80 找到以…

Microsoft SharePoint Server 2010 的新增功能

Microsoft SharePoint Server 2010 包括几个关键的增强和新增功能。重新设计的用户界面中的功能区通过将命令放置到更易于导航的基于任务的选项卡上&#xff0c;来帮助您更快地完成工作。可以跨多个 Internet 浏览器工作&#xff0c;例如 Microsoft Internet Explorer 7.0 和 8…

php四种定界符

1.标准风格 <?php//代码 ?>2.短标记风格 <?//代码 ?>默认情况下是不可以这样写的&#xff0c;我们要到php.ini文件里修改一个配置 找到php.ini文件,我用的是xampp,所以就是以他为例&#xff0c;其他找到php.ini文件方法百度一下就知道了 点击Apache的config&…

php中文乱码问题

访问我的php文件&#xff0c;出现了乱码 解决方法如下&#xff1a; 方法1&#xff1a;加上meta标签&#xff0c;设置字符格式 例如&#xff1a; <?phpecho <meta charset"utf-8">;echo "小河流水人家"; ?>访问就不会乱码了&#xff0c;注…

java 文件转换字符串_java字符串文件互相转换

Java字符串与文件的互转Java中有时候需要读取一个文本类的文件,将其转换为字符串&#xff0c;然后做进一步处理。Java中没有现成的API方法&#xff0c;自己手动实现一个&#xff0c;大家来分享。一、字符串转换为文件/*** 将字符串写入指定文件(当指定的父路径中文件夹不存在时…

php中的echo、print,print_r、var_dump

我们用代码的运行结果来说明 1、echo <?phpheader(content-type:text/html;charsetutf-8);echo "小河流水人家",<br>;echo 10,<br>;echo true,<br>;echo false,<br>;echo array(8),<br>; ?>运行结果 可以输出字符串和数字…

风雨20年:我所积累的20条编程经验 (转)

风雨20年&#xff1a;我所积累的20条编程经验 (转) 编者按&#xff1a;原文作者乔纳森丹尼可&#xff08;Jonathan Danylko&#xff09;是一位自由职业的web架构师和程序员&#xff0c;编程经验已超过20年&#xff0c;涉足领域有电子商务、生物技术、房地产、医疗、保险和公用事…

php的变量、传值、传址、销毁变量

在php中&#xff0c;php的语句需要以**;**结尾&#xff0c;而且变量区分大小写&#xff0c;但关键字不区分大小写 1、变量的命名规则 变量必须以$开头&#xff0c;比如$name&#xff0c;$不是变量名的一部分&#xff0c;仅表示变量名的开始除了$以外&#xff0c;以字母、下划…

php的超全局变量

php的超全局变量如下图 所有的超全局变量都是数组类型&#xff0c;并且php已经帮我们定义好了&#xff0c;下面重点介绍几个 $_GET:用来保存get方式提交的数据 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>测试$_GET…

cmd运行php文件以及环境配置出现的问题、 php.exe不是内部或外部命令,也不是可运行的程序 或批处理文件、PHP startup: Unable to load dynamic library

我用php.exe远行php文件出现了几个问题&#xff0c;先说一下怎么解决这些问题的&#xff0c;然后再说怎么运行 首先是出现 ‘php.exe’ 不是内部或外部命令,也不是可运行的程序 或批处理文件&#xff0c;查了一下&#xff0c;是没有配置php环境变量&#xff0c;配置php环境的过…

php定义常量、判断有没有被定义、预定义常量、显示所有常量

常量一旦被定义&#xff0c;在脚本的其他任何地方都不能被改变&#xff0c;注意&#xff1a;常量名的前面没有$ 语法&#xff1a;define(name,value,case_insensitive ) name:常量名&#xff0c;一般常量名都大写value&#xff1a;常量值case_insensitive &#xff1a;bool类型…

java server模式 设置_JVM client模式和Server模式的区别

这里向大家描述一下JVM client模式和Server模式两者的区别和联系&#xff0c;JVM如果不显式指定是-Server模式还是-client模式&#xff0c;JVM能够根据下列原则进行自动判断(适用于Java5版本或者Java以上版本)。JVM client模式和Server模式JVM Server模式与client模式启动&…

PHP的数据类型、浮点型比较

在介绍php的数据类型前&#xff0c;先说一说强数据类型和弱数据类型。 弱数据类型&#xff1a;变量的类型取决于存放值的类型 强数据类型&#xff1a;变量的类型取决于申明变量时的类型。比如申明变量是A类型就不能存放B类型 PHP是弱数据类型&#xff0c;php支持8种原始数据类型…

《测试驱动开发》读书笔记

最终目标是整洁可用的代码 我们不是从建立对象开始&#xff0c;而是从测试开始 了解需求-》设计测试 -》让测试通过 列出所有已知问题&#xff0c;然后一个一个解决&#xff1b; 培养将软件开发化为一小步一小步开发任务的能力 测试程序与代码所存在的问题不在于重复设计&#…

puppeteer api_使用Node.js和Puppeteer API生成PDF文件

puppeteer apiPuppeteer is a Node library developed by Google and provides a high-level API for developers. Puppeteer是Google开发的Node库&#xff0c;并为开发人员提供了高级API。 With Node.js already up and running, we will install puppeteer via NPM (node pa…

php中进制转换

我们知道&#xff0c;进制有二进制、八进制、十进制、十六进制&#xff0c;但在php中只能存取八进制、十进制、十六进制 在讲进制转换之前&#xff0c;我们先说一下进制单词的缩写&#xff1a; 二进制&#xff1a;bin八进制&#xff1a;oct十进制&#xff1a;dec十六进制&…

python rgb 图像_在Python中查找RGB图像的互补图像

python rgb 图像Complementary image is a transformed image such that it consists of complementary colours of the ones, which is present in the original image. 互补图像是一种变换后的图像 &#xff0c;它由原始图像中存在的互补色组成。 For finding the complemen…

php的字符串、双引号输出变量的问题、转义字符

字符串 php中字符串可以用单引号和双引号表示&#xff0c;但单引号效率比双引号高&#xff0c;因为单引号是真正的字符串&#xff0c;双引号要做运算&#xff0c;即将字符串中的变量替换成值&#xff0c;单引号不需要 看下面的例子 <?phpheader(content-type:text/html;…