看了很多 Trie 树的介绍, 这篇讲的最好,简单易懂(特别是代码部分),直接转载:http://www.cnblogs.com/dolphin0520/archive/2011/10/11/2207886.html

Trie树也称字典树,因为其效率很高,所以在在字符串查找、前缀匹配等中应用很广泛,其高效率是以空间为代价的。

一.Trie树的原理

利用串构建一个字典树,这个字典树保存了串的公共前缀信息,因此可以降低查询操作的复杂度。

下面以英文单词构建的字典树为例,这棵Trie树中每个结点包括26个孩子结点,因为总共有26个英文字母(假设单词都是小写字母组成)。

则可声明包含Trie树的结点信息的结构体:

 #define MAX 26

 typedef struct TrieNode               //Trie结点声明
{
bool isStr; //标记该结点处是否构成单词
struct TrieNode *next[MAX]; //儿子分支
}Trie;

 其中next是一个指针数组,存放着指向各个孩子结点的指针。

如给出字符串"abc","ab","bd","dda",根据该字符串序列构建一棵Trie树。则构建的树如下:

Trie树的根结点不包含任何信息,第一个字符串为"abc",第一个字母为'a',因此根结点中数组next下标为'a'-97的值不为NULL,其他同理,构建的Trie树如图所示,红色结点表示在该处可以构成一个单词。很显然,如果要查找单词"abc"是否存在,查找长度则为O(len),len为要查找的字符串的长度。而若采用一般的逐个匹配查找,则查找长度为O(len*n),n为字符串的个数。显然基于Trie树的查找效率要高很多。

但是却是以空间为代价的,比如图中每个结点所占的空间都为(26*4+1)Byte=105Byte,那么这棵Trie树所占的空间则为105*8Byte=840Byte,而普通的逐个查找所占空间只需(3+2+2+3)Byte=10Byte。

二.Trie树的操作

在Trie树中主要有3个操作,插入、查找和删除。一般情况下Trie树中很少存在删除单独某个结点的情况,因此只考虑删除整棵树。

1.插入

假设存在字符串str,Trie树的根结点为root。i=0,p=root。

1)取str[i],判断p->next[str[i]-97]是否为空,若为空,则建立结点temp,并将p->next[str[i]-97]指向temp,然后p指向temp;

若不为空,则p=p->next[str[i]-97];

2)i++,继续取str[i],循环1)中的操作,直到遇到结束符'\0',此时将当前结点p中的isStr置为true。

2.查找

假设要查找的字符串为str,Trie树的根结点为root,i=0,p=root

1)取str[i],判断判断p->next[str[i]-97]是否为空,若为空,则返回false;若不为空,则p=p->next[str[i]-97],继续取字符。

2)重复1)中的操作直到遇到结束符'\0',若当前结点p不为空并且isStr为true,则返回true,否则返回false。

3.删除

删除可以以递归的形式进行删除。

测试程序:

 #include <iostream>
#include <cstdlib>
#include <stdio.h>
#define MAX 26
using namespace std; typedef struct TrieNode
{
bool isWord;
struct TrieNode *next[MAX];
}Trie; void insert(Trie *root, const char *s)
{
if(root == NULL || (*s) == '\0')
return;
Trie *p = root;
int i;
while((*s) != '\0')
{
if(p->next[(*s) - 'a'] == NULL)
{
Trie *temp = (Trie *)malloc(sizeof(Trie));
for(i = ; i < MAX; ++i)
{
temp->next[i] = NULL;
}
temp->isWord = false;
p->next[(*s) - 'a'] = temp;
p = p->next[(*s) - 'a'];
}
else
{
p = p->next[(*s) - 'a'];
}
s++;
}
p->isWord = true;
}
void del(Trie *root)
{
int i;
for(i = ; i < MAX; ++i)
{
if(root->next[i] != NULL)
{
del(root->next[i]);
}
}
free(root);
} int search(Trie *root, const char *s)
{
Trie *p = root;
while(p != NULL&&*s != '\0')
{
p = p->next[(*s) - 'a'];
s++;
}
return (p != NULL && (p->isWord == true));
}
int main()
{
int i;
int n,m;
char s[];
Trie *root = (Trie *)malloc(sizeof(Trie));
for(i = ; i < MAX; ++i)
{
root->next[i] = NULL;
}
root->isWord = false;
scanf("%d",&n);
getchar();
for(i = ; i < n; ++i)
{
scanf("%s",s);
insert(root, s);
}
while(scanf("%d",&m)!=EOF)
{
for(i = ; i < m; ++i)
{
scanf("%s",s);
if(search(root, s))
{
printf("Yes, find it!\n");
}
else
{
printf("No, loss it!\n");
}
}
}
del(root);
return ;
}

Trie 树(转)的更多相关文章

  1. 基于trie树做一个ac自动机

    基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...

  2. 基于trie树的具有联想功能的文本编辑器

    之前的软件设计与开发实践课程中,自己构思的大作业题目.做的具有核心功能,但是还欠缺边边角角的小功能和持久化数据结构,先放出来,有机会一点点改.github:https://github.com/chu ...

  3. hihocoder-1014 Trie树

    hihocoder 1014 : Trie树 link: https://hihocoder.com/problemset/problem/1014 题意: 实现Trie树,实现对单词的快速统计. # ...

  4. 洛谷P2412 查单词 [trie树 RMQ]

    题目背景 滚粗了的HansBug在收拾旧英语书,然而他发现了什么奇妙的东西. 题目描述 udp2.T3如果遇到相同的字符串,输出后面的 蒟蒻HansBug在一本英语书里面找到了一个单词表,包含N个单词 ...

  5. 通过trie树实现单词自动补全

    /** * 实现单词补全功能 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #incl ...

  6. #1014 Trie树

    本题主要是求构造一棵Trie树,即词典树用于统计单词. C#代码如下: using System; using System.Collections.Generic; using System.Lin ...

  7. Trie树-字典查找

    描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一本词典,于是小Hi就向小Ho提出了那个经典的问题: ...

  8. Trie树的创建、插入、查询的实现

    原文:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=28977986&id=3807947 1.什么是Trie树 Tr ...

  9. Trie树(c++实现)

    转:http://www.cnblogs.com/kaituorensheng/p/3602155.html http://blog.csdn.net/insistgogo/article/detai ...

  10. [转]双数组TRIE树原理

    原文名称: An Efficient Digital Search Algorithm by Using a Double-Array Structure 作者: JUN-ICHI AOE 译文: 使 ...

随机推荐

  1. 20160329javaweb之JSP -cookie入门

    一.什么是会话? •会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话. 会话过程中要解决的一些问题? •每个用户在使用浏览器与服务器 ...

  2. iOS开发-自动布局篇:史上最牛的自动布局教学!

    转载自:http://www.jianshu.com/p/f6cf9ef451d9 本文我们将提到: aotulayout(手码) VFL aotulayout(Xib) Masonry(第三方框架) ...

  3. 漫话JavaScript与异步·第一话——异步:何处惹尘埃

    自JavaScript诞生之日起,频繁与异步打交道便是这门语言的使命,并为此衍生出了许多设计和理念.因此,深入理解异步的概念对于前端工程师来说极为重要. 什么是异步? 程序是分"块" ...

  4. 安装aptana插件报Error opening the editor. java.lang.NullPointerException

    Aptana的官方网站下载eclipse的插件:  http://update.aptana.com/update/studio/3.2/ ,可以在线安装也可以下载插件后再安装,我是以在线的形式安装的 ...

  5. 08_使用TCP/IP Monitor监视SOAP协议

    [SOAP定义] SOAP   简单对象访问协议,基于http传输xml数据,soap协议体是xml格式.SOAP   是一种网络通信协议SOAP   即Simple Object Access Pr ...

  6. 飞锐GIS开发基础系列

    3s知识库和GIS科研站,未经允许,禁止任何形式的复制.转载和传播.联系方式:276888624@qq.com 品GIS,品开发,品人生...... http://www.3sbase.com/3sb ...

  7. linux进程与端口查看命令

    查看程序对应进程号:ps –ef|grep 进程名 查看进程号所占用的端口号:netstat –nltp|grep 进程号 使用lsof命令: lsof –i:端口号

  8. ASP.NET中的母版页

    添加一个"母版页",使用<asp:ContentPlaceHolder>挖坑,新建的母版页已经自动设置了两个ContentPlaceHolder创建使用母版页的具体页面 ...

  9. mini2440移植uboot-2008.10 (一)

    今天是我申请此博客的第一天,从现在开始养成每次学完新东西,都要写博客进行总结的习惯!!!Come on! 首先就从这两天学的uboot开始吧,这两天学这个东西郁闷死了,不知道该怎么去学,尤其是到nan ...

  10. Mysql存储过程知识,案例--mysql存储过程基本函数

    Mysql存储过程知识,案例: create procedure delete_setting(in p_settingid integer) begin delete from setting wh ...