听从德兄说好多东家都喜欢这个东西的。。。
Trie —单词查找树
l 简介
Trie , 又称单词查找树、前缀树,是一种哈希树的变种。应用于字符串的统计与排序,经常被搜索引擎系统用于文本词频统计。
含有单词“ tea ”“ tree ”“ A ”“ ZSU ”的一棵 Trie 。
l 性质
n 根节点不包含字符,除根节点外的每一个节点都只包含一个字符。
n 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
n 每个节点的所有子节点包含的字符都不相同。
l 优点
n 查询快。对于长度为 m 的键值,最坏情况下只需花费 O(m) 的时间;而 BST 最坏情况下需要 O(m log n) 的时间。
n 当存储大量字符串时, Trie 耗费的空间较少。因为键值并非显式存储的,而是与其他键值共享子串。
n Trie 适用于“最长前缀匹配”。
l 操作
n 初始化或清空
遍历 Trie ,删除所有节点,只保留根节点。
n 插入字符串
1. 设置 当前节点 为 根节点 ,设置 当前字符 为插入字符串中的首个字符;
2. 在 当前节点 的子节点上搜索 当前字符 ,若存在,则将 当前节点 设为值为当前字符的子节点;否则新建一个值为 当前字符 的子节点,并将 当前结点 设置为新创建的节点。 .
3. 将 当前字符 设置为串中的下个字符,若 当前字符 为 0 ,则结束;否则转 2.
n 查找字符串
搜索过程与插入操作类似,当字符找不到匹配时返回假;若全部字符都存在匹配,判断最终停留的节点是否为树叶,若是,则返回真,否则返回假。
n 删除字符串
首先查找该字符串,边查询边将经过的节点压栈,若找不到,则返回假;否则依次判断栈顶节点是否为树叶,若是则删除该节点,否则返回真。
l 实现
对于字符表大小为S的字符串集,需建立一个S叉树来代表这些字符串的集合。
l 代码
/* * 版权所有 (C) 2009 喻扬 中山大学
/* 本程序只作学习用途,未经许可,不得用于任何商业目的。
*/
#include < string .h >
/* trie的节点类型 */
template < int Size > // Size为字符表的大小
struct trie_node {
/* 数据成员 */
bool terminable; // 当前节点是否可以作为字符串的结尾
int node; // 子节点的个数
trie_node * child[Size]; // 指向子节点指针
/* 构造函数 */
trie_node() : terminable( false ), node( 0 ) { memset(child, 0 , sizeof (child)); }
} ;
/* trie */
template < int Size, typename Index > // Size为字符表的大小,Index为字符表的哈希函数
class trie {
public :
/* 定义类型别名 */
typedef trie_node < Size > node_type;
typedef trie_node < Size >* link_type;
/* 构造函数 */
trie(Index i = Index()) : index(i)
/* 析构函数 */
~ trie() { clear(); }
/* 清空 */
void clear() {
clear_node(root);
for ( int i = 0 ; i < Size; ++ i) root.child[i] = 0 ;
}
/* 插入字符串 */
template < typename Iterator >
void insert(Iterator begin, Iterator end) {
link_type cur = & root; // 当前节点设置为根节点
for (; begin != end; ++ begin) {
if ( ! cur -> child[index[ * begin]]) { // 若当前字符找不到匹配,则新建节点
cur -> child[index[ * begin]] = new node_type;
++ cur -> node; // 当前节点的子节点数加一
}
cur = cur -> child[index[ * begin]]; // 将当前节点设置为当前字符对应的子节点
}
cur -> terminable = true ; // 设置存放最后一个字符的节点的可终止标志为真
}
/* 插入字符串,针对C风格字符串的重载版本 */
void insert( const char * str)
/* 查找字符串,算法和插入类似 */
template < typename Iterator >
bool find(Iterator begin, Iterator end)
/* 查找字符串,针对C风格字符串的重载版本 */
bool find( const char * str)
/* 删除字符串 */
template < typename Iterator >
bool erase(Iterator begin, Iterator end)
/* 删除字符串,针对C风格字符串的重载版本 */
bool erase( char * str)
/* 按字典序遍历单词树 */
template < typename Functor >
void traverse(Functor & execute = Functor())
private :
/* 访问某结点及其子结点 */
template < typename Functor >
void visit_node(node_type cur, Functor & execute)
/* 清除某个节点的所有子节点 */
void clear_node(node_type cur)
/* 边搜索边删除冗余节点
返回值用于向其父节点声明是否该删除该节点 */
template < typename Iterator >
bool erase_node(Iterator begin, Iterator end, node_type & cur, bool & result)
/* 根节点 */
node_type root;
/* 将字符转换为索引的转换表或函数对象 */
Index index;
} ;
l 参考资料
英文维基 http://en.wikipedia.org/wiki/Trie
中文维基 http://zh.wikipedia.org/w/index.php?title=Trie&variant=zh-cn