Trie树

本文介绍了一种高效的数据结构——字典树(Trie),详细解释了其如何利用字符串的公共前缀来减少查询时间,提高查询效率。文章还提供了字典树的初始化、插入和查询操作的具体代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简介

字典树,trie树,字母树

优点:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

树的每一条上对应一个字符

每个顶点表示的是将根到顶点所经的边上的字符依次连接起来所对应的字符串

称Tire上的边为转移,顶点为状态

如下图样例

红色节点代表该节点为一个字符串的结尾

(白色节点就不是字符串的结尾)

从根节点到红色节点所形成的字符串,就是如图左边的字符串

很容易可以看出,Tire树很好的利用了公共前缀,节约存储空间
在这里插入图片描述

二、操作实现的代码

假设字符集为26个小写英文字母

(一)初始化

1、定义节点

struct node
{
    bool bo; //判断该节点是否为一个字符串
    //也可定义为n,用于记录该字符串数量
    node *next[Z]; //存放子节点,Z为字符集大小
    //可以引入map
};

2、新建节点

每次新建的节点的字符指针均应该指向空

node *Newnode()
{
    node *p = new node; //新建节点
    for (int i = 0; i < 26; i++)
        p->next[i] = NULL; //字符指针均指向空
    p->bo = false;         //修改状态
    return p;              //返回节点指针
}

(二)插入

在插入字符串s时,令一个指针p指向根节点,然后依次遍历s中的的每一个字符c

1、当p的c字符指针指向已存在节点q,则令p=q

2、当p的c字符指针指向空,则新建一个节点q,并且令p=q

3、当字符串s遍历完毕,在当前的节点p上标记它是一个字符串的结尾

void Insert(node *p, string s)//插入一个字符串
{
    for (auto x : s) //遍历字符串
    {
        if (p->next[x - 'a'] == NULL) //不存在,建立新节点
        {
            node *q = Newnode();
            p->next[x - 'a'] = q;
        }
        p = p->next[x - 'a'];//指向下一个节点
    }
    p->bo = true;//遍历完毕,标记上字符串状态
}

(三)查询

在查询字符串s是否存在时,令一个指针p指向根节点,然后依次遍历s中的的每一个字符c

1、当p的c字符指针指向空时,说明s不存在,结束查询,返回false

2、当p的c字符指针指向已存在节点q,则令p=q

3、当字符串s遍历完毕,并且当前节点p被标记为一个字符串结尾,说明s存在,返回true

bool Find(node *p, string s) //查找字符串
{
    for (auto x : s) //遍历该字符串
    {
        if (p->next[x - 'a'] == NULL) //找不到,则返回false
            return false;
        p = p->next[x - 'a'];
    }
    return p->bo; //遍历完毕,返回该节点状态
}

关于删除

tire树一般不会去删除单节点

可以用递归的方式来释放内存空间

总代码

#include <bits/stdc++.h>
using namespace std;
#define Z 30
struct node
{
    bool bo; //判断该节点是否为一个字符串
    //也可定义为n,用于记录该字符串数量
    node *next[Z]; //存放子节点,Z为字符集大小
};
node *Newnode()
{
    node *p = new node; //新建节点
    for (int i = 0; i < 26; i++)
        p->next[i] = NULL; //字符指针均指向空
    p->bo = false;         //修改状态
    return p;              //返回节点指针
}
void Insert(node *p, string s)
{
    for (auto x : s) //遍历字符串
    {
        if (p->next[x - 'a'] == NULL) //不存在,建立新节点
        {
            node *q = Newnode();
            p->next[x - 'a'] = q;
        }
        p = p->next[x - 'a']; //指向下一个节点
    }
    p->bo = true; //遍历完毕,标记上字符串状态
}
bool Find(node *p, string s) //查找字符串
{
    for (auto x : s) //遍历该字符串
    {
        if (p->next[x - 'a'] == NULL) //找不到,则返回false
            return false;
        p = p->next[x - 'a'];
    }
    return p->bo; //遍历完毕,返回该节点状态
}
int main()
{
    node *trie = Newnode(); //建立一个字典树

    string s, ss;
    cin >> s;        //输入字符串
    Insert(trie, s); //插入字符串
    cin >> ss;       //输入要查询的字符串
    cout << (Find(trie, ss) ? "存在" : "不存在");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值