实现前缀树 C#


前言

本博客源自于LeeCode中的一道叫做实现前缀树的题,感觉很有意思,所以专门写一篇博客来记录下;

注意:本文的前缀树只用来简单处理字母类型的字符串;

一、前缀树是什么?什么是前缀树?

理解前缀树:

顾名思义,前缀树是一种和前缀有关的树形结构,两个关键点,前缀和树,树形结构想必都很清楚,一个节点对应多个节点的数据结构称之为树形结构;这里的前缀指字符串的一个字符,作为一个前缀存储在树形结构的节点上,一个字符串的各个字符,依次存储在树形结构的节点上所构成的树, 就是前缀树;
如下图所示:通过前缀树的方式存储了四个单词
在这里插入图片描述

前缀树的定义:

前缀树又名字典树,单词查找树,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。

二、实现前缀树

1.基本结构

包含的元素:
  • 所有子节点:Trie[] children;
  • 标志性变量(表示是否为最后一个字符):bool is_End;
  • 构造函数:初始化26个数组大小是因为在本篇博客要实现的前缀树里,每个节点最多只能包含26个子节点,也就是26个英文字母;
  • 插入方法:public void Insert(string word)
  • 搜索是否已存在了某个单词:public bool Search(string word)
  • 搜索某单词是否为已存储的单词的前缀:`public bool StartsWith(string prefix)
  • 私有工具方法,查找某单词的最后一个节点树:Trie SearchPrefix(string prefix)
public class Trie
    {
    
    
        Trie[] children;
        bool is_End;
        public Trie()
        {
    
    
            children = new Trie[26];
            is_End = false;
        }

        public void Insert(string word)
        {
    
    
        }

        public bool Search(string word)
        {
    
    
        }

        public bool StartsWith(string prefix)
        {
    
    
        }

        Trie SearchPrefix(string prefix)
        {
    
    
        }
    }

2.实现功能

  • 实现插入方法public void Insert(string word) :字符串的每个字符依次存到了对应的分支节点下,如果没有该字母对应的节点,就创建一个,然后获取刚创建的子节点的引用,继续往后依次存储,直到把该字符串全部存完后,将最后一个获取到的树的结束变量设为false;到此,一个单词的树结构插入完成。
     public void Insert(string word)
        {
    
    
            Trie node = this;
            char[] chars = word.ToCharArray();
            for (int i = 0; i < word.Length; i++)
            {
    
    
                char ch = chars[i];
                int index = ch - 'a';
                if (node.children[index]==null)
                {
    
    
                    node.children[index] = new Trie();
                }

                node = node.children[index];		//重点在这里
            }

            node.is_End = true;
        }
  • 实现私有工具方法,查找某单词的最后一个节点树:Trie SearchPrefix(string prefix) :以该树为根节点依次查找每个树的所有子节点,找不到就直接返回空,遍历完就返回最后一个的结果。
        Trie SearchPrefix(string prefix)
        {
    
    
            char[] chars = prefix.ToCharArray();
            Trie node = this;
            for (int i = 0; i < prefix.Length; i++)
            {
    
    
                char ch = chars[i];
                int index = ch - 'a';
                if (node.children[index]==null)
                {
    
    
                    return null;
                }

                node = node.children[index];
            }

            return node;
        }
  • 实现 搜索是否已存在了某个单词:public bool Search(string word) : 通过工具方法获取该单词在树结构内的最后一个子节点,如果该子节点不为空并且是最后一个,则存在;
        public bool Search(string word)
        {
    
    
            Trie node = SearchPrefix(word);
            return node != null && node.is_End;
        }
  • 实现 搜索某单词是否为已存储的单词的前缀:`public bool StartsWith(string prefix) : 不为空,则存在;
        public bool StartsWith(string prefix)
        {
    
    
            return SearchPrefix(prefix) != null;
        }
  • 完整代码
public class Trie
    {
    
    
        Trie[] children;
        bool is_End;
        public Trie()
        {
    
    
            children = new Trie[26];
            is_End = false;
        }

        public void Insert(string word)
        {
    
    
            Trie node = this;
            char[] chars = word.ToCharArray();
            for (int i = 0; i < word.Length; i++)
            {
    
    
                char ch = chars[i];
                int index = ch - 'a';
                if (node.children[index]==null)
                {
    
    
                    node.children[index] = new Trie();
                }

                node = node.children[index];
            }

            node.is_End = true;
        }

        public bool Search(string word)
        {
    
    
            Trie node = SearchPrefix(word);
            return node != null && node.is_End;
        }

        public bool StartsWith(string prefix)
        {
    
    
            return SearchPrefix(prefix) != null;
        }

        Trie SearchPrefix(string prefix)
        {
    
    
            char[] chars = prefix.ToCharArray();
            Trie node = this;
            for (int i = 0; i < prefix.Length; i++)
            {
    
    
                char ch = chars[i];
                int index = ch - 'a';
                if (node.children[index]==null)
                {
    
    
                    return null;
                }

                node = node.children[index];
            }

            return node;
        }
    }```

猜你喜欢

转载自blog.csdn.net/u011229164/article/details/126456548