Trie树概念
别称:单词查找树、字典树
结构:树形结构,哈希树的变种
应用:统计、排序、保存大量字符串
优点:利用公共前缀,减少查询时间和比较次数
树的概念
节点:根节点、父节点、子节点、叶子节点
关系:父子(前驱后继)、兄弟(相同父节点)
Trie树特点
空间换时间
每一个节点都有至少26个子节点(对于单词)
插入、查询时间复杂度都为O(len)
排序按照Trie树先序遍历
节约空间
保存大量单词时候,相同前缀的空间共用
除根节点外,每个节点包含一个字符
从根节点到某一结点的路径,为对应节点的字符串
每个节点的所有子节点包含的字符均不同
Trie树的实现
1 Trie树定义
指向子节点的指针
当前节点的值
struct Trie // 定义Trie树节点结构体 { int value; // 节点的值 Trie *child[26]; // 指向的子节点的指针 Trie() // 构造函数初始化 { value = 0; memset(child, NULL, sizeof(child)); } } *root; // 根节点指针
2 插入过程
从根节点开始,按照字母对应节点不断向下
直到单词结束,在该节点上记录单词信息
void Insert(char str[]) // 插入字符串str { Trie *x = root; // 从根节点开始 for(int i = 0; str[i]; i++) // 逐个插入 { int d = str[i] - 'a'; // 若子节点不存在,则new出对应节点 if(x->child[d] == NULL) x->child[d] = new Trie; x = x->child[d]; // 转成对应子树 } x->vlaue ++; // 表示该单词出现次数 }
从根节点开始搜索
得到第一个字母节点后,转到对应子树
在相应子树继续搜索下一个字母
重复上述操作,直到单词结束,读取节点信息
int Search(char str[]) // 查找字符串str { Trie *x = root; // 从根节点开始 for(int i = 0; str[i]; i++) { int d = str[i] - 'a'; if(x->child[d] == NULL) // 查找失败,直接退出 return 0; x = x->child[d]; // 转成对应子树 } return x->vlaue; // 查找成功,返回节点的值 }
void Deal(Trie*x) // 释放x为根的子树 { if(x == NULL) return ; for(int i = 0; i<26; i++) // 释放x的所有子节点 { if(x->child[i] != NULL) Deal(x->child[i]); } delete x; // 释放x节点空间 }
补充:
动态创建新节点(new)
释放空间(delete),否则会后组数据影响而WA
动态申请新节点耗时太多,数据量大容易TLE
采用静态方式
注意作为“内存”的数组大小,否则容易RE