字典树(多叉树)

实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。

示例:

Trie trie = new Trie();

trie.insert(“apple”);
trie.search(“apple”); // 返回 true
trie.search(“app”); // 返回 false
trie.startsWith(“app”); // 返回 true
trie.insert(“app”);
trie.search(“app”); // 返回 true
说明:

你可以假设所有的输入都是由小写字母 a-z 构成的。
保证所有输入均为非空字符串。

来源:力扣(LeetCode)

总结:
这道题是字典树的应用,在做这道题时花了不少时间,但是确实这个不是什么难题,但是忘记了自定义链表的创建,这个确实是不该。

学习中发现的问题与知识点:
1.结构体可以书写构造函数(方便初始化节点)
2.链表忽略头节点可以更加方便链表的操作。

#include <bits/stdc++.h>
using namespace std;
//字典树的节点
struct Node
{
    //节点的值
    char chr;
    //是否为结尾
    bool end;
    //分支节点
    Node *other;
    //下一级节点
    Node *next;
    //初始化结构体
    Node()
    {
        other=NULL;
        next=NULL;
        end=false;
        chr='\n';
    }
};
class Trie {
    //树的头节点
    Node *header;
    //给与一个头节点,和一个字符,查询这个字符在当前链表中的位置,返回其的指针,不存在时返回末尾最后一个节点的指针
    Node* found(Node *H,char c)
    {
        Node *N = H,*p = H->other;
        while(p!=NULL)
        {
            N = p;
            if(p->chr==c)
                break;
            p=p->other;
        }
        return N;
    }
public:
    //初始化字典树
    Trie() {
        header = new Node();
    }
    
    //向字典树插入一个单词
    void insert(string word) {
        Node *H = header;
        for(int i=0;i<word.size();++i)
        {
            H = found(H,word[i]);
            //检测节点是否被查询到
            if(H->chr!=word[i])
            {
                //没有查询到节点
                //插入将word[i]插入为新节点
                Node *p = new Node();
                p->chr = word[i];
                p->other = H->other;
                H->other = p;
                //创建下一级节点
                p->next = new Node();
                //判断当前节点是否为word的结尾
                if(i+1==word.size())
                    p->end=1;
                H = p->next;
            }
            else
            {
                //查询到节点
                //判断当前节点是否为word的结尾
               if(i+1==word.size())
                    H->end=1;
                H = H->next; 
            }
        }
    }
    
    //查询word是否存在于树中
    bool search(string word) {
        int i=0;
        Node *p = header;
        for(;i<word.size();++i)
        {
            //查询节点
            p = found(p,word[i]);
            //判断是否查询到的节点
            if(p->chr!=word[i])
                break;
            //判断是否为结尾
            if(i+1==word.size()&&p->end)
                return 1;
            p = p->next;
        }
        return 0;
    }
    
    //查询prefix是否为某一个词的前缀
    bool startsWith(string prefix) {
        int i=0;
        Node *p = header;
        for(;i<prefix.size();++i)
        {
            p = found(p,prefix[i]);
            if(p->chr!=prefix[i])
                break;
            if(i+1==prefix.size())
                return 1;
            p = p->next;
        }
        return 0;
    }
};
int main()
{
    Trie trie = Trie();
trie.insert("apple");
cout<<trie.search("apple")<<'\n';   // 返回 true
cout<<trie.search("app")<<'\n';     // 返回 false
cout<<trie.startsWith("app")<<'\n'; // 返回 true
trie.insert("app");   
cout<<trie.search("app")<<'\n';     // 返回 true
system("pause");
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值