前缀树(TrieTree)数据结构
介绍
前缀树(Trietree)是一种数据结构,用于高效地存储和检索字符串。前缀树在搜索引擎、字符串匹配等领域有着广泛的应用。
前缀树的主要特点是通过将字符串拆分为字符序列,并将每个字符作为树的节点来构建树形结构,可以非常高效地进行字符串的插入、搜索和删除操作。
前缀树的应用场景包括:拼写检查和自动补全、敏感词过滤、字符串匹配等应用场景
一、C++实现
这里主要实现了前缀树的插入和查找功能,查找主要包括某个词组是否存在、获取所有以某个前缀开始的所有词组。
代码如下:
#pragma once
#include <string>
#include <unordered_map>
class TrieTree
{
public:
TrieTree()
{
}
~TrieTree()
{
releaseResources(this);
}
// 插入
void insert(const std::string& word)
{
TrieTree* node = this;
for (const auto& c : word)
{
// 创建节点 并指向该节点
if (node->m_map.count(c) == 0)
{
node->m_map[c] = new TrieTree();
}
node = node->m_map[c];
}
// 结尾
node->m_end = true;
}
// 查找
bool search(const std::string& word)
{
TrieTree* node = findWord(word);
bool succeed = false;
if (node != nullptr)
{
// 结尾
succeed = node->m_end;
}
return succeed;
}
// 查找前缀为word的字符串是否存在
bool startWith(const std::string& word)
{
TrieTree* node = findWord(word);
return node != nullptr; // 查找完成
}
// 查找所有以word为前缀的词组
std::list<std::string> getWordsWithPrefix(const std::string& word)
{
std::list<std::string> words;
if (word.empty())
return words;
// 不存在前缀
TrieTree* node = findWord(word);
if (node == nullptr)
return words;
recursiveSearch(node, word, words);
return words;
}
private:
// 递归查找
void recursiveSearch(TrieTree* node, std::string word, std::list<std::string>& words)
{
// 递归出口
if (node->m_end)
{
words.push_back(word);
return;
}
for (const auto& n : node->m_map)
{
char c = n.first;
TrieTree* next = node->m_map[c];
recursiveSearch(next, word + c, words);
}
}
// 查找word最后所在的节点
TrieTree* findWord(const std::string& word)
{
TrieTree* node = this;
for (const auto& c : word)
{
if (node->m_map.count(c) == 0)
return nullptr;
node = node->m_map[c];
}
return node;
}
// 释放内存
void releaseResources(TrieTree* node)
{
if (node->m_map.empty())
return;
for (const auto& val : node->m_map)
{
TrieTree* s = val.second;
delete s;
}
node->m_map.clear();
}
private:
bool m_end = false;
std::unordered_map<char, TrieTree*> m_map;
};
二、使用方法
可以读取外部文件构建前缀树,这里的示例直接用一段文字构建前缀树,并查询所有以"一"为前缀的词组。
代码如下:
#include <sstream>
#include "TrieTree.h"
int main(int argc, char* argv[])
{
TrieTree tree;
std::string content = std::string(
"时间就是金钱 "
"珍惜时间 "
"一寸光阴一寸金 "
"寸金难买寸光阴 "
"一年之计在于春 "
"一日之计在于晨 ");
std::istringstream stream(content);
std::string text;
// 分割' '
while (getline(stream, text, ' '))
tree.insert(text);
// 查找以 "一" 为前缀的所有词组
std::list<std::string> words = tree.getWordsWithPrefix("一");
for (const auto& w : words)
{
// do something
}
return 0;
}
144

被折叠的 条评论
为什么被折叠?



