字典树的定义(引自点击打开链接)
又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。
字典树与字典很相似,当你要查一个单词是不是在字典树中,首先看单词的第一个字母是不是在字典的第一层,如果不在,说明字典树里没有该单词,如果在就在该字母的孩子节点里找是不是有单词的第二个字母,没有说明没有该单词,有的话用同样的方法继续查找.字典树不仅可以用来储存字母,也可以储存数字等其它数据。
字典树详解(结合HDU1251)
1.字典树结构定义详解
typedef struct TrieNode //trie的数据结构定义
{
int n; // 该节点作为前缀出现的次数
struct TrieNode *next[MAX]; //next为指向结构体自身的一个空指针数组,用来存放下一节点的地址 //空指针数组可以存放任何数的地址。
} TrieNode;
TrieNode Memory[1000000]; //先分配好内存。 malloc 较为费时
int m = 0;
2.初始化一个节点
TrieNode * createTrieNode() //创建新节点,这里开辟的是头结点,只用来存放下一个节点的地址以及初始化自身指向的结构体成员的n=1以及next=null
{
TrieNode * tmp = &Memory[m++]; //将指向结构体的数组的首地址赋值给同样指向结构体的指针变量tmp
tmp->n = 1; //则该节点作为前缀的次数为1
for (int i = 0; i < MAX; i++) //开辟新的节点,因为不确定新的节点的地址,所以要将所有可能插入的位置都列出来,26种情况
tmp->next[i] = NULL; //新建节点的地址为0
return tmp; //返回新建的节点
}
3.插入节点
void insertTrie(TrieNode * * proot, char * str) //TrieNode **proot表示的意思是proot是一个地址,存放的是首节点的地址,传入的是需要插入的字符串数组的首地址
{
TrieNode * tmp = *proot; //将首节点的地址赋值给结构体指针类型变量tmp
int i = 0, k;
//从第一个字符开始,一个一个的插入字符
while (str[i]) //表示存在第一节点
{
k = str[i] - 'a'; //当前字符应该插入的位置
if (tmp->next[k]) //如果下一个节点存在
{
tmp->next[k]->n++; //则当前节点作为前缀的次数增加1
}
else //如果下一节点不存在
{
tmp->next[k] = createTrieNode();//开辟一个新的节点
}
tmp = tmp->next[k];//将下一个节点的地址存放在上一个节点的地址中,即让上一节点指向下一节点
i++; //移到下一个字符
}
4.搜索字符串
int searchTrie(TrieNode * root, char * str) //在字典树种搜索字符串数组,需要传入的是结构体类型指针变量即头结点以及需要搜索的字符串数组的首地址
{
if (root == NULL) //若节点数为0
return 0; //返回搜索值0,即没有找到这个字符
TrieNode * tmp = root; //将头节点赋值给结构体变量tmp
int i = 0, k; //从搜索字符串的第一个字符开始搜索
while (str[i]) //如果这个字母存在
{
k = str[i] - 'a'; //确定这个字母的位置
if (tmp->next[k]) //如果下一个字符存在
{
tmp = tmp->next[k]; //把这个字符的地址赋值给tmp
}
else //如果这个字符不存在
return 0; 返回搜索值0,即没有找到这个字符串
i++; //移到下一个字符
}
return tmp->n; //返回最后的那个字符 所在节点的n,即搜索字符串作为前缀出现的次数
}
5.主函数
int main()
{
char s[10]; //声明每一个字符串的长度范围
TrieNode *root = createTrieNode(); //定义结构体类型指针变量root即头结点,并初始化这个头结点
while (gets(s) && s[0] != '\0') //输入要插入的字符串以及输入结束的条件“\0”,也就是说想要结束输入字符串就多输入一个回车键
{
insertTrie(&root, s);//将输入的字符串从第一个字符开始依次插入,传入的是字符串数组的首地址以及头结点root的的的地址
}
while (gets(s)) //查询输入的字符串
{
printf("%d\n", searchTrie(root, s)); //输出查询函数的返回值,
}
特别提醒:编译的时候记得选择c++,不然会出现错误