【C++数据结构】Trie树

具体的Trie树结构请自行查找,下面只说我自己那部分的理解。

①Trie树是一棵多叉树,那么管理好子结点对树的性能有很大的帮助,为了通用,我使用了红黑树结构作为子结点的管理结构。当然如果是查找英文串什么的,可以使用数组或者哈希。

②Trie树是一棵前缀树,对前缀处理方便,我在此对后缀情况不作处理。

③Trie树不宜随便删除结点,因此我也不提供删除功能,只提供修改功能。

 

关于Trie树我的实现:

①为减少数组的拷贝,每一个结点使用红黑树结构(map)来存放子结点,其中子结点的值作为key值,子结点指针作为value,但是子结点不存放值。

②从直观上看,Trie树被改造成key-value形式,并且key需要是可迭代的。当插入新的串,需要获得key的迭代器,以迭代的值作为结点的值,迭代到最后的值的结点,存放value;而中间迭代的结点不存放值。因此判断串是否存在时,传入key,通过判断迭代访问后获得的结点中是否存放值即可。

③插入功能,不存在时创建,存在时修改。

④提供前缀查询功能。

 

下面是C++代码的实现:

编译环境:GCC 7.3、VS 2005

#ifndef __TRIE_TREE_H__
#define __TRIE_TREE_H__

#if __cplusplus >= 201103L
#include <type_traits> // std::forward、std::move
#endif

#if __cplusplus >= 201103L
#define null nullptr
#else
#define null NULL
#endif 

#include <map>

template<typename _Tp>
struct Comparator
{
	int operator()(const _Tp &a1, const _Tp &a2) const
	{ return a1 < a2; }
};

template<typename _KeyType, 
typename _ValueType,
typename _CompareType = Comparator<_KeyType> >
class TrieTree
{
public:
	typedef _KeyType    key_type;
	typedef _ValueType  value_type;
	typedef const _KeyType & const_reference;

public:
	struct TTreeNode;
	typedef std::map<_KeyType, TTreeNode*, _CompareType>  container_type;

public:
	struct TTreeNode
	{
		typedef _ValueType*   pointer;
		typedef unsigned long size_type;

		typedef TTreeNode self;

		TTreeNode(pointer p = null)
			: _M_value(p) { }

		TTreeNode(const self &) { }

#if __cplusplus >= 201103L
		TTreeNode(self &&node)
			: _M_children(std::move(node._M_children)), _M_value(node._M_value)
		{ node._M_value = null; }
#endif

		~TTreeNode()
		{
			typename container_type::iterator it = _M_children.begin();
			while(it != _M_children.end())
			{ delete (it++)->second; }
			if(null != _M_value)
			{ delete _M_value; }
		}

		self* child(const key_type &v)
		{ 
			typename container_type::iterator found = _M_children.find(v);
			return found != _M_children.end() ? found->second : null;
		}

		size_type child_size() const 
		{ return static_cast<size_type>(_M_children.size()); }

		self* append_child(const key_type &v)
		{ 
			typename container_type::iterator found = _M_children.find(v);
			return found == _M_children.end() ? (_M_children[v] = new self()) : found->second;
		}

		pointer value() const
		{ return _M_value; }

		container_type _M_children;
		pointer        _M_value;
	};

public:
	typedef TTreeNode  node_type;
	typedef TTreeNode* node_pointer;

	typedef TrieTree<_KeyType, _ValueType, _CompareType> self;

public:
	TrieTree() { }

	TrieTree(const self &) { }

#if __cplusplus >= 201103L 
	TrieTree(self &&tree)
		: _M_root(std::move(tree._M_root)) { }

	template<typename _ForwardIterator, typename ... Args>
	TrieTree(_ForwardIterator b, _ForwardIterator e, Args && ... args)
	{ insert(b, e, std::forward<Args>(args)...); }

	template<typename _ForwardIterator, typename ... Args>
	node_pointer insert(_ForwardIterator b, _ForwardIterator e, Args && ... args)
	{
		if(b == e)
		{ return null; }

		node_pointer node = &_M_root;
		while(b != e)
		{ node = node->append_child(*b++); }

		node->_M_value = new value_type(std::forward<Args>(args)...);
		return node;
	}

	template<typename _Type, typename ... Args>
	node_pointer insert(const _Type &key_list, Args && ... args)
	{ return insert(key_list.begin(), key_list.end(), std::forward<Args>(args)...); }

	template<typename _Type>
	node_pointer insert(const _Type &key_list, value_type &&v)
	{ return insert(key_list.begin(), key_list.end(), std::move(v)); }

#else
	template<typename _ForwardIterator>
	TrieTree(_ForwardIterator b, _ForwardIterator e, const value_type &v)
	{ insert<_ForwardIterator>(b, e, v); }

	template<typename _ForwardIterator>
	node_pointer insert(_ForwardIterator b, _ForwardIterator e, const value_type &v)
	{
		if(b == e)
		{ return null; }

		node_pointer node = &_M_root;
		while(b != e)
		{ node = node->append_child(*b++); }

		node->_M_value = new value_type(v);
		return node;
	}

#endif
	template<typename _Type>
	node_pointer insert(const _Type &key_list, const value_type &v)
	{
		typedef typename _Type::const_iterator __citer;
		return insert<__citer>(key_list.begin(), key_list.end(), v);
	}

	template<typename _ForwardIterator>
	bool contain(_ForwardIterator b, _ForwardIterator e)
	{
		if(b == e)
		{ return false; }

		node_pointer node = &_M_root;
		while(b != e)
		{ 
			node = node->child(*b++); 

			if(null == node)
			{ return false; }
		}

		return null != node;
	}

	template<typename _ForwardIterator>
	bool contain(_ForwardIterator b, _ForwardIterator e) const 
	{ return const_cast<self*>(this)->contain<_ForwardIterator>(b, e); }

	template<typename _Type>
	bool contain(const _Type &key_list)
	{
		typedef typename _Type::const_iterator __citer;
		return contain<__citer>(key_list.begin(), key_list.end());
	}
	template<typename _Type>
	bool contain(const _Type &key_list) const
	{ return const_cast<self*>(this)->contain<_Type>(key_list); }

	template<typename _ForwardIterator>
	node_pointer find(_ForwardIterator b, _ForwardIterator e)
	{
		if(b == e)
		{ return null; }

		node_pointer node = &_M_root;
		while(b != e)
		{ 
			node = node->child(*b++); 

			if(null == node || (node->child_size() == 0 && null == node->_M_value))
			{ return null; }
		}

		if(null == node->_M_value)
		{ return null; }

		return node;
	}

	template<typename _ForwardIterator>
	const node_pointer find(_ForwardIterator b, _ForwardIterator e) const
	{ return const_cast<self*>(this)->find<_ForwardIterator>(b, e); }

	template<typename _Type>
	node_pointer find(const _Type &key_list)
	{
		typedef typename _Type::const_iterator __citer;
		return find<__citer>(key_list.begin(), key_list.end());
	}

	template<typename _Type>
	const node_pointer find(const _Type &key_list) const
	{ return const_cast<self*>(this)->find<_Type>(key_list); }

	template<typename _ForwardIterator>
	bool exists(_ForwardIterator b, _ForwardIterator e) const 
	{ return null != const_cast<self*>(this)->find<_ForwardIterator>(b, e); }

	template<typename _Type>
	bool exists(const _Type &key_list) const 
	{ 
		typedef typename _Type::const_iterator __citer;
		return exists<__citer>(key_list.begin(), key_list.end()); 
	}

	template<typename _Type>
	node_pointer operator[](const _Type &key_list)
	{ return find<_Type>(key_list); }

	value_type& value(node_pointer p)
	{ return *p->value(); }

private:
	node_type _M_root;
};

#endif // __TRIE_TREE_H__

测试代码:

#include <iostream>
#include <string>
#include <cstring>
#include "trie_tree.h"

static std::string shield[] = 
{
	"aaaa",
	"aaaaabbbbbb",
	"a*b*c*d"
};

static const char *check[] = 
{
	"aaa",
	"aaaaabbbbbb",
	"b"
};

static void func2()
{
	typedef TrieTree<char, bool> tree;

	// 屏蔽字测试

	tree t;
	for(std::size_t i = 0; i < sizeof(shield) / sizeof(std::string); ++i)
	{
		t.insert<std::string>(shield[i], true);
	}

	std::cout << std::boolalpha;
	for(std::size_t i = 0; i < sizeof(check) / sizeof(const char *); ++i)
	{
		std::cout << "\"" << check[i] << "\" is shield? : " << t.exists<const char*>(check[i], check[i] + strlen(check[i])) << std::endl;
	}
}

static void func()
{
	typedef TrieTree<char, bool> tree;

	const char *ch = "aadfasf";
	const char *str = "aad";
	std::string tmp = ch;
	tree t;
	t.insert<std::string>(tmp, true);

	if(t.exists<std::string>(tmp))
	{
		std::cout << "exists11111111" << std::endl;
		tree::node_pointer p = t.find<std::string>(tmp);
		std::cout << std::boolalpha << "value: " << t.value(p) << std::endl;
	}
	if(t.exists<const char*>(ch, ch + strlen(ch)))
	{
		std::cout << "exists222222" << std::endl;
	}

	if(t.exists<const char *>(str, str + strlen(str)))
	{
		std::cout << "exists33333" << std::endl;
	}

	if(t.contain<const char *>(str, str + strlen(str)))
	{
		std::cout << "contain" << std::endl;
	}
}


int main() 
{
	func();
	func2();
	system("pause");
	return 0;
}

运行结果如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值