具体的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;
}
运行结果如下: