前缀树(TrieTree)数据结构的C++实现

前缀树(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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值