C ++ tree data structure --Trie

Specific Trie tree structure your own search, said the following just understand that part of my own.

①Trie tree is more than one tree, then manage the child node of great help for the performance of the tree, for general purpose, I used the red-black tree structure as a child node management structure. Of course, if it is looking for English string or something, you can use an array or hash.

②Trie tree is a prefix tree, easy to deal with prefixes, suffixes me in this case not be processed.

③Trie tree should not just delete nodes, so I do not provide a delete function only available modification.

 

About the Trie my implementation:

① In order to reduce the copy of the array, each node using a red-black tree structure (Map) to hold the child node, wherein the value of the sub-node as the key value, as a child node pointer value, but does not store the value of the child node.

② Intuitively, Trie tree is transformed into the form of key-value and key needs to be iterative. When inserting the new string, the key need iterator to the iteration value as the value of the node, the last node to the iterative value, stored value; the intermediate node does not store the iteration value. When it is determined whether there is a string, the incoming key, the node by determining whether to iterate the obtained value can be stored.

③ insertion to create does not exist, modify presence.

④ provide a prefix search function.

 

Here is the C ++ code:

Compiler environment: 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__

Test code:

#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;
}

Results are as follows:

Published 22 original articles · won praise 3 · Views 3939

Guess you like

Origin blog.csdn.net/qq811299838/article/details/104765330