字典树(单词查找树)

一、

字典树主要用于前缀搜索,字典树不仅可以用来存储字母,也可以存储数字等其他数据。

二、

应用:统计、排序、保存大量字符串

原理:利用公共前缀,减少查询时间和比较次数

三、

特点:空间换时间

1.每一个节点都有至少26个子节点(英文字母)

2.插入、查询时间复杂度为O(len)

3.排序按照Trie树先序遍历

节约空间

1.保存大量单词的时候,相同前缀的空间共用。大部分字符串具有相同的前缀,即公共前缀。

2.每个节点,对应一项前缀,叶子节点对应最长前缀,即单词本身。

四、

性质:

1.根节点不包含字母

2.除根节点外,每个节点包含一个字符

3.从根节点到某一节点的路径,为对应节点的字符串

4.每个节点的所有子节点包含的字符均不同

五、

字典树的静态实现:

Trie树定义:1.指向子节点的指针

2.当前节点的值

struct Trie//定义Trie树节点结构体
{
    int value;//节点的值
    Trie *child[26];//指向的子节点的指针
    Trie()
    {
        value = 0;
        memset(child, NULL, sizeof(child));
    }
}*root;//根节点指针
//插入过程:1.从根节点开始,按照字母对应节点不断向下
//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->value++;//表示该单词出现次数
}
//查找过程1.从根节点开始搜索
//2.得到第一个字母节点后,转到对应子树
//3.在相应子树继续搜索下一个字母
//4.重复上述操作,直到到此结束,读取节点信息
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->value;//查找成功,返回节点的值
}
//动态创建新节点
//1.释放空间(delete),否则会后组数据影响而WA
//2.动态申请新节点耗时太多,数据量大容易TLE
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节点空间
}
//采用静态方式
//注意作为“内存”的数组大小,否则容易RE
struct Trie//定义Trie树节点结构体
{
    int value;//节点的值
    int child[26];//指向的子节点的下标
    Trie()//构造函数
    {
        value = 0;
        memset(child, 0, sizeof(child));
    }
}trie[MAX];//静态地址空间数组
int trieN = 0;//静态数组下标,也表示节点数
//插入
void Insert(char str[])//插入字符串str
{
    int x = 0;//从根节点开始
    for (int i = 0; str[i]; i++)//逐个插入
    {
        int d = str[i] - 'a';
        if (trie[x].child[d] == 0)//在静态数组末尾取一节点
        {
            trie[++trieN] = Trie();
            trie[x].child[d] = trieN;
        }
        x = trie[x].child[d];//转成对应子树
    }
    trie[x].value++;//表示该单词出现次数
}

//查找
int Search(char str[])//查找字符串str
{
    int x = 0;//从根节点开始
    for (int i = 0; str[i]; i++)
    {
        int d = str[i] - 'a';
        if (trie[x].child[d] == 0)//查找失败,直接退出
            return 0;
        x = trie[x].child[d];//转成对应子树
    }
    return trie[x].value;//查找成功,返回节点的值
}

 

posted @ 2016-11-28 10:57  web之路  阅读(1393)  评论(0编辑  收藏  举报