版权声明:本文作者靖心,靖空间地址:http://blog.csdn.net/kenden23/,未经本作者同意不得转载。

https://blog.csdn.net/kenden23/article/details/24453639

Trie是非常高效的信息检索数据结构, 时间效率会是O(m),当中m是须要搜索的keyword的长度。

缺点就是须要的存储空间大。

Trie的特点:

1. 每一个Trie的节点都由多个分支构成

2. 每一个分支代表可能的keyword的一个字符

3. 须要mark(标志)每一个keyword的最后一个字符为leaf node(叶子节点)

英文字母的节点数据结构能够表演示样例如以下:

struct TrieNode
{
int value; /* Used to mark leaf nodes */
TrieNode *children[ALPHABET_SIZE];
};

插入keyword:

1. keyword的每一个字符都作为独立的trie节点, 注意每一个子节点都是一组指针,指向下一个trie节点。

2 假设输入的keyword是新的,或者是比原有keyword长, 就须要构造新的节点, 并且须要标志它的结束点为叶子节点。 

3. 假设keyword比原有的某个keyword短,那么就能够仅仅标志新的叶子节点。

4. keyword的长度决定了trie的深度

搜索keyword:

1. 比較keyword的字符。然后往下一层移动

2. 假设keyword结束,或者没有这个字符在trie中,那么搜索结束。 前者比較最后一个节点是否是叶子节点,假设是表示搜索成功,否则不成功。后者表示搜索不成功。

參考原文:

http://www.geeksforgeeks.org/trie-insert-and-search/

实现程序:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string> #define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])
#define ALPHABET_SIZE (26)
#define CHAR_TO_INDEX(c) ((int)c - (int)'a') struct TrieNode
{
int value; /* Used to mark leaf nodes */
TrieNode *children[ALPHABET_SIZE];
}; struct TrieT
{
TrieNode *root;
int count;
}; // Returns new trie node (initialized to NULLs)
TrieNode *getNode(void)
{
TrieNode *pNode = NULL;
pNode = (TrieNode *)malloc(sizeof(TrieNode)); if( pNode )
{
int i;
pNode->value = 0;
for(i = 0; i < ALPHABET_SIZE; i++)
{
pNode->children[i] = NULL;
}
}
return pNode;
} // Initializes trie (root is dummy node)
void initialize(TrieT *pTrie)
{
pTrie->root = getNode();
pTrie->count = 0;
} // If not present, inserts key into trie
// If the key is prefix of trie node, just marks leaf node
void insert(TrieT *pTrie, char key[])
{
int level = 0;
int length = strlen(key);
int index = 0;
TrieNode *pCrawl; pTrie->count++;
pCrawl = pTrie->root; for( level = 0; level < length; level++ )
{
index = CHAR_TO_INDEX(key[level]);
if( !pCrawl->children[index] )
{
pCrawl->children[index] = getNode();
}
pCrawl = pCrawl->children[index];
}
// mark last node as leaf
pCrawl->value = pTrie->count;
} // Returns non zero, if key presents in trie
int search(TrieT *pTrie, char key[])
{
int level;
int length = strlen(key);
int index;
TrieNode *pCrawl; pCrawl = pTrie->root;
for( level = 0; level < length; level++ )
{
index = CHAR_TO_INDEX(key[level]);
if( !pCrawl->children[index] )
{
return 0;
}
pCrawl = pCrawl->children[index];
}
return (0 != pCrawl && pCrawl->value);
} // Driver
int main()
{
// Input keys (use only 'a' through 'z' and lower case)
char keys[][8] = {"the", "a", "there", "answer", "any", "by", "bye", "their"};
TrieT trie; char output[][32] = {"Not present in trie", "Present in trie"}; initialize(&trie); // Construct trie
for(int i = 0; i < ARRAY_SIZE(keys); i++)
{
insert(&trie, keys[i]);
} // Search for different keys
printf("%s --- %s\n", "the", output[search(&trie, "the")] );
printf("%s --- %s\n", "these", output[search(&trie, "these")] );
printf("%s --- %s\n", "their", output[search(&trie, "their")] );
printf("%s --- %s\n", "thaw", output[search(&trie, "thaw")] ); return 0;
}

更新 2014 5 -16

C++写的类,主要是带构造函数和析构函数。能够非常好管理内存,甚至不须要递归地手动释放内存了,析构函数能够自己主动递归调用释放全部Node,这个是C++比C强大的地方之中的一个:

class TrieInsertAndSearch
{
const static int ALPH_SIZE = 26; struct Node
{
int val;
Node *children[ALPH_SIZE];
explicit Node(int v = 0) : val(v)
{
for (int i = 0; i < ALPH_SIZE; i++)
{
children[i] = nullptr;
}
}
~Node()
{
for (int i = 0; i < ALPH_SIZE; i++)
{
if (children[i]) delete children[i];
children[i] = nullptr;
}
}
};
struct Tree
{
Node *root;
int count;
explicit Tree(int c = 0, Node *r = nullptr) : count(c), root(r){}
~Tree()
{
if (root) delete root;
root = nullptr;
}
}; Tree *pT;
void insert(char key[])
{
int len = strlen(key);
Node *pCrawl = pT->root;
pT->count++;
for (int lv = 0; lv < len; lv++)
{
int id = key[lv] - 'a';
if (!pCrawl->children[id])
{
pCrawl->children[id] = new Node;
}
pCrawl = pCrawl->children[id];
}
pCrawl->val = pT->count;
}
bool search(char key[])
{
int len = strlen(key);
Node *pCrawl = pT->root;
for (int lv = 0; lv < len; lv++)
{
int id = key[lv] - 'a';
if (!pCrawl->children[id]) return false;
pCrawl = pCrawl->children[id];
}
return (pCrawl && pCrawl->val);
}
public:
TrieInsertAndSearch()
{
char keys[][8] = {"the", "a", "there", "answer", "any", "by", "bye", "their"};
pT = new Tree(0, new Node);
int n = sizeof(keys) / sizeof(keys[0]);
for (int i = 0; i < n; i++)
{
insert(keys[i]);
} // Search for different keys
if (search("the")) printf("the is in Trie\n");
else printf("the is not in Trie\n");
if (search("these")) printf("these is in Trie\n");
else printf("these is not in Trie\n");
if (search("their")) printf("their is in Trie\n");
else printf("their is not in Trie\n");
if (search("thaw")) printf("thaw is in Trie\n");
else printf("thaw is not in Trie\n");
}
~TrieInsertAndSearch()
{
if (pT) delete pT;
pT = nullptr;
}
};

GeekforGeeks Trie - 键树简单介绍 - 构造 插入 和 搜索的更多相关文章

  1. UE4中的AI行为树简单介绍

    UE4引擎中可以实现简单AI的方式有很多,行为树是其中比较常用也很实用的AI控制方式,在官网的学习文档中也有最简单的目标跟踪AI操作教程,笔者在这里只作简单介绍. AIController->和 ...

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

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

  3. 萌新笔记——C++里创建 Trie字典树(中文词典)(一)(插入、遍历)

    萌新做词典第一篇,做得不好,还请指正,谢谢大佬! 写了一个词典,用到了Trie字典树. 写这个词典的目的,一个是为了压缩一些数据,另一个是为了尝试搜索提示,就像在谷歌搜索的时候,打出某个关键字,会提示 ...

  4. C++里创建 Trie字典树(中文词典)(一)(插入、遍历)

    萌新做词典第一篇,做得不好,还请指正,谢谢大佬! 写了一个词典,用到了Trie字典树. 写这个词典的目的,一个是为了压缩一些数据,另一个是为了尝试搜索提示,就像在谷歌搜索的时候,打出某个关键字,会提示 ...

  5. SQL 数据库 学习 007 通过一个示例简单介绍什么是字段、属性、列、元组、记录、表、主键、外键 (上)

    SQL 数据库 学习 007 通过一个示例简单介绍什么是字段.属性.列.元组.记录.表.主键.外键 (上) 我们来介绍一下:数据库是如何存储数据的. 数据库是如何存储数据的 来看一个小例子 scott ...

  6. BST&AVL&红黑树简单介绍

    (BST&AVL&红黑树简单介绍) 前言: 节主要是给出BST,AVL和红黑树的C++代码,方便自己以后的查阅,其代码依旧是data structures and algorithm ...

  7. 算法设计和数据结构学习_5(BST&AVL&红黑树简单介绍)

    前言: 节主要是给出BST,AVL和红黑树的C++代码,方便自己以后的查阅,其代码依旧是data structures and algorithm analysis in c++ (second ed ...

  8. python利用Trie(前缀树)实现搜索引擎中关键字输入提示(学习Hash Trie和Double-array Trie)

    python利用Trie(前缀树)实现搜索引擎中关键字输入提示(学习Hash Trie和Double-array Trie) 主要包括两部分内容:(1)利用python中的dict实现Trie:(2) ...

  9. 《PHP 5.5从零開始学(视频教学版)》内容简单介绍、文件夹

    <PHP 5.5从零開始学(视频教学版)>当当网购买地址: http://product.dangdang.com/23586810.html <PHP 5.5从零開始学(视频教学版 ...

随机推荐

  1. 转载:JS进度条

    转载地址:http://blog.csdn.net/treeClimber/article/details/569974 代码在原基础上稍作改动,如下: <!DOCTYPE HTML PUBLI ...

  2. 利用gearman同步mysql数据到redis

    一.Gearman 1.Gearman是一个分发任务的程序框架. 2.体系:a.client:发送一个jobb.server:找到合适的worker,把job交给该workerc.worker:处理j ...

  3. ajax个人学习笔记

    1. function createXHR(){ if(typeof XMLHttpRequest != 'undefined'){ return new XMLHttpRequest(); }els ...

  4. 给mysql root用户设置密码

    使用其他用户进入数据库, 用select PASSWORD('你要设置的密码'), 然后直接update mysql.user set  mysql.user.Password='你PASSWORD( ...

  5. 利用python 掌握机器学习的过程

    转载:http://python.jobbole.com/84326/ 偶然看到的这篇文章,觉得对我挺有引导作用的.特此跟大家分享一下. 为了理解和应用机器学习技术,你需要学习 Python 或者 R ...

  6. (一)spark算子 分为3大类

    value类型的算子 处理数据类型为value型的算子(也就是这个算子只处理数据类型为value的数据),可以根据rdd的输入分区与输出分区的关系分为以下几个类型 (1)输入分区与输出分区一对一型 m ...

  7. 【JMeter4.0学习(十一)】之JMeter对(Mysql、Oracle)数据库性能测试脚本开发

    一.MySQL数据库链接: 注:下面所产生的问题一律参考详见:<[JMeter4.0]之遇到的问题总结(持续更新)>(包括Mysql.Orcale) 准备:引包,包路径一定要放对位置,参考 ...

  8. 用代码构造PreferenceScreen

    在PreferenceFregment中构造界面,简单省事的方法就是使用findPreference然后在xml里把UI写好.在代码中动态的添加UI内容也是需要的.核心代码是: PreferenceS ...

  9. ps -ef 和 aux 区别

    Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信 ...

  10. ubuntu 1204 安装mysql

    检測本机是否有安装mysql sudo netstat -tap | grep mysql 运行上面的命令之后.看到 mysq 的socket 处于监听状态,说明有成功安装. 安装mysql sudo ...