赞
踩
字典树,它跟我们查字典的步骤类似,打个比方,我们在查字典的时候会首先查第一个字母,然后在继续寻找第二个字母,以此类推直到找到对应的单词。
这个过程和用于字符匹配的字典树一样,假如我们在字典树第二层已经找不到第一个字母了(第一层为Root, 不用于表示字符),那么表示这个单词根本不存在字典树里;假设第一个字母找到了,那么继续在下一层寻找下一个字符,依次往下层匹配字符,直到匹配到叶子节点或者不存在。它是树形结构,如下图所示:
以空间换时间,利用字符串的公共前缀来降低时间开销,最大限度的减少无谓的字符串比较。
字典树不仅可以用来存储字符,也可以用来存储数字。
先给出字典表,然后在给出单词,查找单词是否在字典中。
刚好碰到一个题目,要求执行上面的操作。先输入5个单词存为字典,然后查找下面的2个单词是否在字典表中,存在输出 yes, 否则输出 false.
5
you
me
love
have
colorful
2
your
colorful
false
true
#include <stdio.h>
const int SIZE = 26; //26个字母
//字典树结构体
typedef struct Node_
{
bool isLeaf; //是否为叶子节点
Node_ *child[SIZE]; //每个字符的表示
}Node;
Node tree[10000];
//获取字符串长度
int getLen(char *s)
{
int ret = 0;
while(s[ret]) ret++;
return ret;
}
//初始化tree数组,每个孩子都为空,表示当前还是空树
void init()
{
for(int i = 0; i < 10000; i++)
{
for(int j = 0; j < SIZE; j++)
{
tree[i].isLeaf = false;
tree[i].child[j] = NULL;
}
}
}
int main()
{
init();
int num;
scanf("%d", &num);
int cnt = 0;
Node *root = &tree[cnt++]; //根节点不表示字符
char c[21];
for(int i = 0; i < num; i++)
{
scanf("%s", c);
int len = getLen(c);
//建立字典树
Node* p = root;
for(int j = 0; j < len; j++)
{
int index = c[j] - 'a'; //表示对应的字符
if(p->child[index] == NULL)
p->child[index] = &tree[cnt++]; //为字符分配地址
p = p->child[index];
}
p->isLeaf = true;//当前节点为根节点,用于判断是否存在于字典树中
}
int T;
scanf("%d", &T);
for(int i = 0; i < T; i++)
{
scanf("%s", c);
int len = getLen(c);
int count = 0;
int index;
//查询字典树
Node* p = root;
while(p && count < len)
{
index = c[count] - 'a';//对应字符
p = p->child[index];//对应的字符有分配地址,表示匹配到
count++;
}
if(p && p->isLeaf)//节点存在并且为叶子节点,说明在字典树中存在这个单词
printf("#%d true", i+1);
else
printf("#%d false", i+1);
printf("\n");
}
return 0;
}
本文原创首发于微信公众号 [ 林里少年 ],欢迎关注第一时间获取更新。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。