字典树(Trie tree)

来源:互联网 发布:30岁男士护肤 知乎 编辑:程序博客网 时间:2024/05/17 08:31
Trie,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。
性质:
根节点不包含字符,除根节点外每一个节点都只包含一个字符。
从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。

每个节点的所有子节点包含的字符都不相同。

Trie树的基本实现
字母树的插入(Insert)、删除( Delete)和查找(Find)都非常简单,用一个一重循环即可,即第i 次循环找到前i 个字母所对应的子树,然后进行相应的操作。实现这棵字母树,我们用最常见的数组保存(静态开辟内存)即可,当然也可以开动态的指针类型(动态开辟内存)。至于结点对儿子的指向,一般有三种方法:
1、对每个结点开一个字母集大小的数组,对应的下标是儿子所表示的字母,内容则是这个儿子对应在大数组上的位置,即标号;
2、对每个结点挂一个链表,按一定顺序记录每个儿子是谁;
3、使用左儿子右兄弟表示法记录这棵树。
三种方法,各有特点。第一种易实现,但实际的空间要求较大;第二种,较易实现,空间要求相对较小,但比较费时;第三种,空间要求最小,但相对费时且不易写。

现就第一种给出实现代码:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <mcheck.h> #define TREE_WIDTH 256#define WORDLENMAX 128 struct trie_node {struct trie_node *next[TREE_WIDTH];};void insert(struct trie_node *tree, char *str){int i = 0;unsigned char c;while((c = str[i]) != '\0') {if(tree->next[c] == NULL) {tree->next[c] = malloc(sizeof(struct trie_node));memset(tree->next[c], 0, sizeof(struct trie_node));}tree = tree->next[c];i++;}}int isExist(struct trie_node *tree, char *str){int i = 0;unsigned char c;if(!tree)return 0;while((c = str[i]) != '\0') {if(tree->next[c] == NULL)break;tree = tree->next[c];i++;}if(c != '\0')return 0;for(i = 0; i < TREE_WIDTH; i++) {if(tree->next[i])return 0;}return 1;}void delete(struct trie_node *tree, char *str){int i = 0, j, child_num;struct trie_node **path;unsigned char c;if(!tree)return;if(!isExist(tree, str))return;path = malloc(strlen(str) * sizeof(struct trie_node *));while((c = str[i]) != '\0') {path[i] = tree;tree = tree->next[c];i++;}free(tree);for(i = strlen(str) - 1; i >= 0; i--) {child_num = 0;for(j = 0; j < TREE_WIDTH; j++) {if(path[i]->next[j])child_num++;}if(child_num == 1 && i != 0)free(path[i]);else {path[i]->next[str[i]]= NULL;break;}}free(path);}void __print(struct trie_node *tree, unsigned char *str, int len){int i, leaf_node = 1;if(!tree)return;for(i = 0; i < TREE_WIDTH; i++) {if(tree->next[i]) {str[len++] = i;__print(tree->next[i], str, len);leaf_node = 0;}}if(len > 0 && leaf_node == 1) {str[len] = '\0';printf("%s\n", str);}}void print(struct trie_node *tree){unsigned char str[WORDLENMAX];int i = 0;__print(tree, str, i);}void free_trie(struct trie_node *tree){int i;if(!tree)return;for(i = 0; i < TREE_WIDTH; i++) {if(tree->next[i])free_trie(tree->next[i]);}free(tree);}struct trie_node *create_trie(){struct trie_node *tree = malloc(sizeof(struct trie_node));return tree;}int main(){struct trie_node *tree;setenv("MALLOC_TRACE", "memory_report", 1);mtrace();tree = create_trie();insert(tree, "trie_test");insert(tree, "mytrie");printf("%d\n", isExist(tree, "mytrie"));delete(tree, "mytrie");printf("%d\n", isExist(tree, "mytrie"));print(tree);free_trie(tree);return 0;}

测试结果为:



0 0
原创粉丝点击