前言
最近无聊,用70%C和30%C++写了个Trie树的源程序,源码可在CodeBlocks、VC++等上面运行
Trie树
含义:
Trie树,即字典树,又称单词查找树,是一种树形结构,是一种哈希树的变种。
典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以
经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀
来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
三个基本性质:
1.根节点不包含字符,除根节点外每一个节点都只包含一个字符;
2.从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串;
3.每个节点的所有子节点包含的字符都不相同。
简而言之,Trie树就是根据公共前缀来存储元素的多叉树吧(下图转载)
一.题目要求
1)初始化
2)插入元素
3)删除元素
4)查找元素
5)Trie树的应用
二.数据结构体
typedef struct TrieNode {
struct TrieNode *next[Max];//(256个Ascll码)
int if_end;//判断结点是否某元素最后一个字符
int node_count; //子next的数量
char word;//储存一个字符
} TrieNode, *TrieNodePtr, *TrieSTPtr;
三.主要函数
1. 插入函数 void Trie_insert(TrieNodePtr root,char *word)
包含的参数:Trie数的根节点root , 插入元素的字符串地址word。
返回值:(无返回值)。
2.查找函数 int searchTrie(TrieNodePtr root,char *word)
包含的参数:Trie数的根节点root , 查询元素的字符串地址word。
返回值:(int类型)如果存在就返回1,不存在就返回0。
3.删除函数
TrieNodePtr Trie_delect(TrieNodePtr root,char *word,int locate)
包含的参数:Trie数的某节点root,被删除元素的字符串地址word和该元素
的第locate个字符。
返回值:(结构图指针类型)返回值是否NULL决定了递归时要进行的操作
四.函数块及其解析
1.插入函数
trie树是一棵多叉树,它的插入要遵循相邻两个结点存储的字符不能相同这
一规则,并且新建结点要用calloc使其结点内容初始化为空,若是已存在该
结点,它的父母结点的子节点数要加1,若是已到达插入元素的最后一个
结点,需要把最后一个结点的元素结束标志改为TRUE。
void Trie_insert(TrieNodePtr root, char *word){
int i = 0;
TrieSTPtr tmp = root;
while (*(word + i) != '\0') {
int Ascll=*(word + i);//将字符转为其Ascll码
/*
如果树里面没有这个字符,就录入
*/
if (tmp->next[abs(Ascll)] == NULL)//用abs是先前出于中文汉字输入的考虑。但是最终放弃,干脆也不删除了。
{
tmp->next[abs(Ascll)] = (TrieNode *)calloc(1, sizeof(TrieNode));
tmp->next[abs(Ascll)]->word=*(word+i);
tmp->node_count++;//在进入新的字符结点之前,旧结点记录的next数量要加1。
}
tmp = tmp->next[abs(Ascll)];
i++;
}
tmp->if_end = TRUE;//出循环代表整个元素所有字符录入完毕,需要在最后一个字符结点做个元素标记
}
2.查找函数
查找函数在判断条件上类似于插入函数,如果元素的某个字符在Trie树
中不存在对应结点,说明不存在该元素,直接结束查找。如果所有
字符均存在且最后一个字符结点的元素结束标志是TRUE,元素存在。
int searchTrie(TrieNodePtr root,char *word) {
if(root==NULL) {
printf("该Trie树未初始化!\n");
return 0 ;
}
TrieNodePtr tmp=root;
int i=0;
while(word[i]!='\0') {
int Ascll=abs(word[i]);
if(tmp->next[Ascll]==NULL){
printf("没有该元素(或已删除)!\n");return 0 ;}
else tmp=tmp->next[Ascll];
i++;
}
if (tmp->if_end == TRUE){
printf(