patricia trie的实现要点是将度为一的连续分支节点压缩为一串字符串为索引的单一分支节点,从而达到节省空间的目的,是在普通Trie树上的改进
第一种实现:分支节点用map容器
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <stack>
#include <random>
using namespace std;
enum Compare_Result { EQUAL, LEFT_IS_PREFIX, RIGHT_IS_PREFIX, NOT_EQUAL };
struct CompareFunc
{
bool operator()(const vector<char>* const & left, const vector<char>* const & right) const //支持字符串中包含'\0'字符
{
if (left->empty())
return true;
if (right->empty())
return false;
if ((*left)[0] < (*right)[0])
return true;
return false;
}
};
struct TrieTreeNode //Trie树节点类型
{
enum NodeType { DATANODE, BRANCHNODE } type_flag; //节点类型标志,分支节点或存放关键字的叶节点
union
{
string key_in_trie; //叶节点关键字
map<vector<char>*, TrieTreeNode*, CompareFunc> sub_ptr; //分支节点的分支字符和对应的指向分支字符对应的子节点的指针之间的映射关系
};
TrieTreeNode(const string& k) :type_flag(NodeType::DATANODE), key_in_trie(k) {}
TrieTreeNode() :type_flag(NodeType::BRANCHNODE), sub_ptr() {}
TrieTreeNode(TrieTreeNode& be_copied)
{
switch (be_copied.type_flag)
{
case NodeType::DATANODE: new (&key_in_trie) string(be_copied.key_in_trie); break;
case NodeType::BRANCHNODE:
{
new (&sub_ptr) map<vector<char>*, TrieTreeNode*, CompareFunc>();
for (map<vector<char>*, TrieTreeNode*, CompareFunc>::iterator p = be_copied.sub_ptr.begin(); p != be_copied.sub_ptr.end(); ++p)
{
sub_ptr.insert(make_pair(new vector<char>(*(p->first)), nullptr));
}
}
break;
}
type_flag = be_copied.type_flag;
}
~TrieTreeNode()
{
switch (type_flag)
{
case NodeType::DATANODE: key_in_trie.~string(); break;
case NodeType::BRANCHNODE:
{
for (auto p = sub_ptr.begin(); p != sub_ptr.end(); ++p)
{
delete p->first;
}
sub_ptr.~map<vector<char>*, TrieTreeNode*, CompareFunc>(); break;
}
}
}
};
class TrieTree
{
public:
bool insert(const string& be_inserted) const; //Trie树中插入关键字,true成功false失败
bool deleteElem(const string& be_deleted) const; //Trie树中删除指定关键字,true成功false失败
TrieTreeNode* copy(); //拷贝Trie树,返回指向副本Trie树的指针
TrieTree() { root = new TrieTreeNode(); }
TrieTree(TrieTree& be_copied) { root = be_copied.copy(); }
void print(TrieTreeNode* cur, size_t height, size_t offset, const vector<size_t>& height_to_length) const;
void printTrieTree(TrieTreeNode* cur, size_t offset) const;
void printTrieTree(TrieTreeNode* root) const;
bool isEmpty() const { return root->sub_ptr.empty(); }
TrieTreeNode* getTrieTree() const { return root; }
~TrieTree();
private:
template <typename T>
Compare_Result static strCompare(const string& left, const T& right, string::size_type& i, typename T::size_type &j);
TrieTreeNode* root; //Trie树根节点
};
ostream& operator<<(ostream& o, const TrieTree& be_output)
{
if (be_output.isEmpty())
{
o << "NULL" << endl;
return o;
}
cout << "非对齐打印结果:" << endl;
be_output.printTrieTree(be_output.getTrieTree(), 0);
cout << "对齐打印结果:" << endl;
be_output.printTrieTree(be_output.getTrieTree());
return o;
}
template <typename T>
Compare_Result static TrieTree::strCompare(const string& left, const T& right, string::size_type& i, typename T::size_type& j)
{
for (; ; ++i, ++j)
{
if (i == left.size() && j == right.size())
return Compare_Result::EQUAL;
else if (i == left.size() || j == right.size())
{
if (i == left.size())
return Compare_Result::LEFT_IS_PREFIX;
else
return Compare_Result::RIGHT_IS_PREFIX;
}
else if (left[i] != right[j])
return Compare_Result::NOT_EQUAL;
}
}
bool TrieTree::deleteElem(const string& be_deleted) const
{
TrieTreeNode* run = root;
map<vector<char>*, TrieTreeNode*, CompareFunc>::iterator pp_it;
{
map<vector<char>*, TrieTreeNode*, CompareFunc>::iterator p_it;
string::size_type run_index = 0;
while (true)
{
if (run_index < be_deleted.size())
{
{
vector<char> temp(1, be_deleted[run_index]);
p_it = run->sub_ptr.find(&temp);
}
if (p_it == run->sub_ptr.end())
return false;
++run_index;
Compare_Result compare_result;
{
vector<char>::size_type run_on_prefix = 1;
compare_result = strCompare(be_deleted, *(p_it->first), run_index, run_on_prefix);
}
if (compare_result == Compare_Result::NOT_EQUAL || compare_result == Compare_Result::LEFT_IS_PREFIX)
return false;
if (p_it->second->type_flag == TrieTreeNode::NodeType::DATANODE)
{
break;
}
pp_it = p_it;
run = p_it->second;
}
else
{
if (run->sub_ptr.empty() || run->sub_ptr.begin()->first->empty() == false)
return false;
p_it = run->sub_ptr.begin();
break;
}
}
{
string::size_type run_on_leaf = run_index;
if (p_it->first->empty() == false && strCompare(be_deleted, p_it->second->key_in_trie, run_index, run_on_leaf) != Compare_Result::EQUAL)
return false;
}
delete p_it->second;
delete p_it->first;
run->sub_ptr.erase(p_it);
}
if (run != root && run->sub_ptr.size() == 1)
{
if (run->sub_ptr.begin()->second->type_flag == TrieTreeNode::NodeType::BRANCHNODE)
pp_it->first->insert(pp_it->first->end(), run->sub_ptr.begin()->first->begin(), run->sub_ptr.begin()->first->end());
else
pp_it->first->erase(pp_it->first->begin() + 1, pp_it->first->end());
pp_it->second = run->sub_ptr.begin()->second;
delete run;
}
return true;
}
bool TrieTree::insert(const string& be_inserted) const
{
string::size_type run_index = 0;
TrieTreeNode* run = root;
pair<map<vector<char>*, TrieTreeNode*, CompareFunc>::iterator, bool> it;
while (run->type_flag == TrieTreeNode::NodeType::BRANCHNODE)
{
if (run_index < be_inserted.size())
{
vector<char>* temp_ptr = new vector<char>(1, be_inserted[run_index]);
TrieTreeNode* temp_ptr_trie = new TrieTreeNode(be_inserted);
it = run->sub_ptr.insert(make_pair(temp_ptr, temp_ptr_trie));
if (it.second)
return true;
delete temp_ptr;
delete temp_ptr_trie;
++run_index;
vector<char>::size_type run_on_prefix = 1;
Compare_Result compare_result = strCompare(be_inserted, *(it.first->first), run_index, run_on_prefix);
run = it.first->second;
if (compare_result == Compare_Result::NOT_EQUAL || compare_result == Compare_Result::LEFT_IS_PREFIX)
{
it.first->second = new TrieTreeNode();
it.first->second->sub_ptr.insert(make_pair(new vector<char>(it.first->first->begin() + run_on_prefix, it.first->first->end()), run));
it.first->first->erase(it.first->first->begin() + run_on_prefix, it.first->first->end());
if (compare_result == Compare_Result::NOT_EQUAL)
it.first->second->sub_ptr.insert(make_pair(new vector<char>(1, be_inserted[run_index]), new TrieTreeNode(be_inserted)));
else
it.first->second->sub_ptr.insert(make_pair(new vector<char>(), new TrieTreeNode(be_inserted)));
return true;
}
}
else
{
if (run->sub_ptr.empty() || run->sub_ptr.begin()->first->empty() == false)
{
run->sub_ptr.insert(make_pair(new vector<char>(), new TrieTreeNode(be_inserted)));
return true;
}
return false;
}
}
Compare_Result compare_result;
{
string::size_type start_index = run_index;
{
string::size_type run_on_str = run_index;
compare_result = strCompare(be_inserted, run->key_in_trie, run_index, run_on_str);
}
if (compare_result == Compare_Result::EQUAL)
return false;
it.first->second = new TrieTreeNode();
if (start_index != run_index)
it.first->first->insert(it.first->first->end(), be_inserted.begin() + start_index, be_inserted.begin() + run_index);
}
if (compare_result == Compare_Result::LEFT_IS_PREFIX)
{
it.first->second->sub_ptr.insert(make_pair(new vector<char>(), new TrieTreeNode(be_inserted)));
it.first->second->sub_ptr.insert(make_pair(new vector<char>(1, run->key_in_trie[run_index]), run));
}
else if (compare_result == Compare_Result::RIGHT_IS_PREFIX)
{
it.first->second->sub_ptr.insert(make_pair(new vector<char>(), run));
it.first->second->sub_ptr.insert(make_pair(new vector<char>(1, be_inserted[run_index]), new TrieTreeNode(be_inserted)));
}
else
{
it.first->second->sub_ptr.insert(make_pair(new vector<char>(1, run->key_in_trie[run_index]), run));
it.first->second->sub_ptr.insert(make_pair(new vector<char>(1, be_inserted[run_index]), new TrieTreeNode(be_inserted)));
}
return true;
}
TrieTree::~TrieTree()
{
TrieTreeNode* run = root;
stack<pair<TrieTreeNode*, map<vector<char>*, TrieTreeNode*, CompareFunc>::iterator>> work_stack;
bool trace_back_flag = true;
while (true)
{
if (trace_back_flag == true)
{
if (run == root)
{
if (run->sub_ptr.begin() == run->sub_ptr.end())
{
delete root;
return;
}
}
else
{
if (run->type_flag == TrieTreeNode::DATANODE)
{
delete run;
run = work_stack.top().first;
++work_stack.top().second;
//work_stack.top().second = run->sub_ptr.erase(work_stack.top().second);
trace_back_flag = false;
continue;
}
}
work_stack.push(make_pair(run, run->sub_ptr.begin()));
run = run->sub_ptr.begin()->second;
}
else
{
if (run == root || work_stack.top().second != run->sub_ptr.end())
{
if (run == root)
{
if (work_stack.top().second == root->sub_ptr.end())
{
delete root;
return;
}
}
run = work_stack.top().second->second;
trace_back_flag = true;
}
else
{
delete run;
work_stack.pop();
run = work_stack.top().first;
++work_stack.top().second;
//work_stack.top().second = run->sub_ptr.erase(work_stack.top().second);
}
}
}
}
TrieTreeNode* TrieTree::copy()
{
TrieTreeNode* be_copied = root;
stack<pair<TrieTreeNode*, map<vector<char>*, TrieTreeNode*, CompareFunc>::iterator>> work_stack;
stack<pair<TrieTreeNode*, map<vector<char>*, TrieTreeNode*, CompareFunc>::iterator>> copy_trace_stack;
TrieTreeNode* root_of_copy = nullptr;
bool trace_back_flag = true;
while (true)
{
if (trace_back_flag == true)
{
if (be_copied == root)
{
root_of_copy = new TrieTreeNode(*be_copied);
if (be_copied->sub_ptr.begin() == be_copied->sub_ptr.end())
break;
copy_trace_stack.push(make_pair(root_of_copy, root_of_copy->sub_ptr.begin()));
}
else
{
if (work_stack.top().second != work_stack.top().first->sub_ptr.begin())
++copy_trace_stack.top().second;
copy_trace_stack.top().second->second = new TrieTreeNode(*be_copied);
if (be_copied->type_flag != TrieTreeNode::DATANODE)
copy_trace_stack.push(make_pair(copy_trace_stack.top().second->second, copy_trace_stack.top().second->second->sub_ptr.begin()));
else
{
be_copied = work_stack.top().first;
trace_back_flag = false;
continue;
}
}
work_stack.push(make_pair(be_copied, be_copied->sub_ptr.begin()));
be_copied = be_copied->sub_ptr.begin()->second;
}
else
{
map<vector<char>*, TrieTreeNode*, CompareFunc>::iterator tempit = work_stack.top().second;
if (tempit->second->type_flag != TrieTreeNode::DATANODE)
copy_trace_stack.pop();
if (be_copied == root || ++(work_stack.top().second) != be_copied->sub_ptr.end())
{
if (be_copied == root)
{
if (++(work_stack.top().second) == root->sub_ptr.end())
break;
}
be_copied = work_stack.top().second->second;
trace_back_flag = true;
}
else
{
work_stack.pop();
be_copied = work_stack.top().first;
}
}
}
return root_of_copy;
}
void TrieTree::print(TrieTreeNode* cur, size_t height, size_t offset, const vector<size_t> &height_to_length) const
{
if (cur->type_flag == TrieTreeNode::BRANCHNODE)
{
size_t max_length = height_to_length[height];
size_t temp_length;
for (map<vector<char>*, TrieTreeNode*, CompareFunc>::iterator run = cur->sub_ptr.begin(); run != cur->sub_ptr.end(); ++run)
{
for (size_t go = 1; go <= offset; ++go)
cout << " ";
temp_length = max_length;
if (run->first->empty())
{
cout << "NULL";
temp_length -= 4;
}
else
{
for (vector<char>::iterator go = (*run->first).begin(); go != (*run->first).end(); ++go)
cout << *go;
temp_length -= (*run->first).size();
}
for (size_t i = 1; i <= temp_length; ++i)
cout << " ";
cout << "|-" << endl;
print(run->second, height + 1, offset + max_length + 2, height_to_length);
}
}
else
{
for (size_t go = 1; go <= offset; ++go)
cout << " ";
cout << "leaf:" << cur->key_in_trie << endl;
}
}
void TrieTree::printTrieTree(TrieTreeNode* root) const //放到运算符<<函数里调用
{
vector<TrieTreeNode*>* cur_level = new vector<TrieTreeNode*>(1, root);
vector<TrieTreeNode*>* next_level = new vector<TrieTreeNode*>();
vector<size_t> height_to_length;
while (cur_level->empty() == false)
{
int M = 0;
for (size_t run = 0; run < cur_level->size(); ++run)
{
int max_length;
if ((*cur_level)[run]->sub_ptr.begin()->first->empty())
max_length = 4;
else
{
if ((*cur_level)[run]->sub_ptr.begin()->second->type_flag == TrieTreeNode::NodeType::BRANCHNODE)
next_level->push_back((*cur_level)[run]->sub_ptr.begin()->second);
max_length = (*cur_level)[run]->sub_ptr.begin()->first->size();
}
for (map<vector<char>*, TrieTreeNode*, CompareFunc>::iterator go = ++(*cur_level)[run]->sub_ptr.begin(); go != (*cur_level)[run]->sub_ptr.end(); ++go)
{
if (go->second->type_flag == TrieTreeNode::NodeType::BRANCHNODE)
{
next_level->push_back(go->second);
if ( max_length < go->first->size())
max_length = go->first->size();
}
}
if (M < max_length)
M = max_length;
}
height_to_length.push_back(M);
cur_level->clear();
swap(cur_level, next_level);
}
delete cur_level;
delete next_level;
print(root, 0, 0, height_to_length);
}
void TrieTree::printTrieTree(TrieTreeNode* cur, size_t offset) const
{
if (cur->type_flag == TrieTreeNode::BRANCHNODE)
{
size_t max_length;
if (cur->sub_ptr.begin()->first->empty())
max_length = 4;
else
max_length = cur->sub_ptr.begin()->first->size();
for (map<vector<char>*, TrieTreeNode*, CompareFunc>::iterator run = ++cur->sub_ptr.begin(); run != cur->sub_ptr.end(); ++run)
{
if (max_length < run->first->size())
max_length = run->first->size();
}
size_t temp_length;
for (map<vector<char>*, TrieTreeNode*, CompareFunc>::iterator run = cur->sub_ptr.begin(); run != cur->sub_ptr.end(); ++run)
{
for (size_t go = 1; go <= offset; ++go)
cout << " ";
temp_length = max_length;
if (run->first->empty())
{
cout << "NULL";
temp_length -= 4;
}
else
{
for (vector<char>::iterator go = (*run->first).begin(); go != (*run->first).end(); ++go)
cout << *go;
temp_length -= (*run->first).size();
}
for (size_t i = 1; i <= temp_length; ++i)
cout << " ";
cout << "|-" << endl;
printTrieTree(run->second, offset + max_length + 2);
}
}
else
{
for (size_t go = 1; go <= offset; ++go)
cout << " ";
cout << "leaf:" << cur->key_in_trie << endl;
}
}
int main()
{
vector<string> test = { "bluebird", "bunting", "bobwhite", "bluejay", "blud" };
TrieTree test_obj;
for (vector<string>::iterator p = test.begin(); p != test.end(); ++p)
{
cout << "插入字符串" << *p << endl;
if (test_obj.insert(*p))
{
cout << "插入成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "插入失败" << endl;
exit(0);
}
}
cout << endl;
// TrieTreeNode *copy = test_ptr.copy();
//for (vector<string>::iterator p = test.begin(); p != test.end(); ++p)
{
cout << "删除字符串" << "bobwhite" << endl;
if (test_obj.deleteElem("bobwhite"))
{
cout << "删除成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "删除失败" << endl;
exit(0);
}
cout << "删除字符串" << "bluejay" << endl;
if (test_obj.deleteElem("bluejay"))
{
cout << "删除成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "删除失败" << endl;
exit(0);
}
}
cout << endl;
string mod = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
const int L = 9; // 随机字符串最大长度
const int r = 2; //相同长度重复次数
vector<int> LList(L);
vector<string> random_str;
for (int run = 0; run < LList.size(); ++run)
LList[run] = run + 1;
shuffle(LList.begin(), LList.end(), default_random_engine());
for (int re = 1; re <= r; ++re)
{
for (int run = 0; run < LList.size(); ++run)
{
string r;
for (int go = 1; go <= LList[run]; ++go)
{
r.append(1, mod[rand() % mod.size()]);
}
random_str.push_back(r);
}
}
for (vector<string>::iterator p = random_str.begin(); p != random_str.end(); ++p)
{
cout << "插入字符串" << *p << endl;
if (test_obj.insert(*p))
{
cout << "插入成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "插入失败" << endl;
exit(0);
}
}
cout << endl;
// TrieTreeNode *copy = test_ptr.copy();
for (vector<string>::iterator p = random_str.begin(); p != random_str.end(); ++p)
{
cout << "删除字符串" << *p << endl;
if (test_obj.deleteElem(*p))
{
cout << "删除成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "删除失败" << endl;
exit(0);
}
}
cout << endl;
random_str.clear();
for (int i = 1; i <= 7; ++i)
{
string temp(mod, 0, i);
for (int run = 1; run <= 7; ++run)
{
string r;
for (int go = 1; go <= run; ++go)
{
r.append(1, mod[rand() % mod.size()]);
}
random_str.push_back(temp + r);
}
}
cout << "测试字符串有共同前缀不相等情形" << endl;
for (vector<string>::iterator p = random_str.begin(); p != random_str.end(); ++p)
{
cout << "插入字符串" << *p << endl;
if (test_obj.insert(*p))
{
cout << "插入成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "插入失败" << endl;
exit(0);
}
}
cout << endl;
// TrieTreeNode *copy = test_ptr.copy();
for (vector<string>::iterator p = random_str.begin(); p != random_str.end(); ++p)
{
cout << "删除字符串" << *p << endl;
if (test_obj.deleteElem(*p))
{
cout << "删除成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "删除失败" << endl;
exit(0);
}
}
cout << endl;
shuffle(mod.begin(), mod.end(), default_random_engine());
for (string::size_type i = 1; i <= mod.size(); ++i)
{
string temp(mod, 0, i);
cout << "插入字符串" << mod << "的前缀" << temp << endl;
if (test_obj.insert(temp))
{
cout << "插入成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "插入失败" << endl;
exit(0);
}
}
for (string::size_type i = 1; i <= mod.size(); ++i)
{
string temp(mod, 0, i);
cout << "删除字符串" << mod << "的前缀" << temp << endl;
if (test_obj.deleteElem(temp))
{
cout << "删除成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "删除失败" << endl;
exit(0);
}
}
return 0;
}
第二种实现:分支节点用二维Vector数组
#include <iostream>
#include <utility>
#include <vector>
#include <string>
#include <stack>
#include <random>
#include <algorithm>
#include <deque>
#include <tuple>
using namespace std;
enum Compare_Result { EQUAL, LEFT_IS_PREFIX, RIGHT_IS_PREFIX, NOT_EQUAL }; //本实现字符串中不能有'\0'字符
struct TrieTreeNode //Trie树节点类型
{
enum NodeType { DATANODE, BRANCHNODE } type_flag; //节点类型标志,分支节点或存放关键字的叶节点
struct BranchNode
{
vector<pair<vector<char>*, TrieTreeNode*>> sub_ptr;
size_t num;
BranchNode() :sub_ptr(128, make_pair(nullptr, nullptr)), num(0) {}
~BranchNode()
{
if (num != 0)
{
for (auto p = sub_ptr.begin(); ; ++p)
{
if (p->second != nullptr)
{
--num;
delete p->first;
if (num == 0)
break;
}
}
}
sub_ptr.~vector<pair<vector<char>*, TrieTreeNode*>>();
}
BranchNode(const BranchNode& be_copied)
{
new (&sub_ptr) vector<pair<vector<char>*, TrieTreeNode*>>(128, make_pair(nullptr, nullptr));
num = 0;
if (be_copied.num != 0)
{
for (size_t i = 0; ; ++i)
{
if (be_copied.sub_ptr[i].second != nullptr)
{
++num;
if (be_copied.sub_ptr[i].first != nullptr)
sub_ptr[i].first = new vector<char>(*(be_copied.sub_ptr[i].first));
if (num == be_copied.num)
break;
}
}
}
}
};
union
{
string key_in_trie; //叶节点关键字
BranchNode branch_ptr; //分支节点的分支字符和对应的指向分支字符对应的子节点的指针之间的映射关系
};
TrieTreeNode(const string& k) :type_flag(NodeType::DATANODE), key_in_trie(k) {}
TrieTreeNode() :type_flag(NodeType::BRANCHNODE), branch_ptr() {}
TrieTreeNode(TrieTreeNode& be_copied)
{
switch (be_copied.type_flag)
{
case NodeType::DATANODE: {new (&key_in_trie) string(be_copied.key_in_trie); break; }
case NodeType::BRANCHNODE:
{
new (&branch_ptr) BranchNode(be_copied.branch_ptr);
}
break;
}
type_flag = be_copied.type_flag;
}
~TrieTreeNode()
{
switch (type_flag)
{
case NodeType::DATANODE: key_in_trie.~string(); break;
case NodeType::BRANCHNODE:
{
branch_ptr.~BranchNode(); break;
}
}
}
};
class TrieTree
{
public:
bool insert(const string& be_inserted) const; //Trie树中插入关键字,true成功false失败
bool deleteElem(const string& be_deleted) const; //Trie树中删除指定关键字,true成功false失败
TrieTreeNode* copy(); //拷贝Trie树,返回指向副本Trie树的指针
TrieTree() { root = new TrieTreeNode(); }
void print(TrieTreeNode* cur, size_t level, size_t offset, vector<size_t>& height_to_length) const;
void printTrieTree(TrieTreeNode* root) const;
void printTrieTree(TrieTreeNode* cur, size_t offset) const;
bool isEmpty() const { return root->branch_ptr.num == 0; }
TrieTreeNode* getTrieTree() const { return root; }
TrieTree(TrieTree& be_copied) { root = be_copied.copy(); }
~TrieTree();
private:
static size_t char_to_index(const char& ch)
{
return ch;
}
template <typename T>
Compare_Result static strCompare(const string& left, const T& right, string::size_type& i, typename T::size_type& j);
TrieTreeNode* root; //Trie树根节点
};
ostream& operator<<(ostream& o, const TrieTree& be_output)
{
if (be_output.isEmpty())
{
o << "NULL" << endl;
return o;
}
cout << "非对齐打印结果" << endl;
be_output.printTrieTree(be_output.getTrieTree(), 0);
cout << "对齐打印结果" << endl;
be_output.printTrieTree(be_output.getTrieTree());
return o;
}
template <typename T>
Compare_Result static TrieTree::strCompare(const string& left, const T& right, string::size_type& i, typename T::size_type& j)
{
for (; ; ++i, ++j)
{
if (i == left.size() && j == right.size())
return Compare_Result::EQUAL;
else if (i == left.size() || j == right.size())
{
if (i == left.size())
return Compare_Result::LEFT_IS_PREFIX;
else
return Compare_Result::RIGHT_IS_PREFIX;
}
else if (left[i] != right[j])
return Compare_Result::NOT_EQUAL;
}
}
bool TrieTree::deleteElem(const string& be_deleted) const
{
TrieTreeNode* run = root;
pair<vector<char>*, TrieTreeNode*> *father = nullptr;
{
pair<vector<char>*, TrieTreeNode*> *cur = nullptr;
string::size_type run_index = 0;
while (true)
{
if (run_index < be_deleted.size())
{
cur = &run->branch_ptr.sub_ptr[char_to_index(be_deleted[run_index])];
if (cur->second == nullptr)
return false;
++run_index;
Compare_Result compare_result;
{
if (cur->first == nullptr)
{
if (run_index == be_deleted.size())
compare_result = Compare_Result::EQUAL;
else
compare_result = Compare_Result::RIGHT_IS_PREFIX;
}
else
{
vector<char>::size_type run_on_prefix = 0;
compare_result = strCompare(be_deleted, *(cur->first), run_index, run_on_prefix);
}
}
if (compare_result == Compare_Result::NOT_EQUAL || compare_result == Compare_Result::LEFT_IS_PREFIX)
return false;
if (cur->second->type_flag == TrieTreeNode::NodeType::DATANODE)
break;
father = cur;
run = cur->second;
}
else
{
if (run->branch_ptr.num == 0 || run->branch_ptr.sub_ptr[0].second == nullptr)
return false;
cur = &run->branch_ptr.sub_ptr[0];
break;
}
}
{
string::size_type run_on_leaf = run_index;
if (&run->branch_ptr.sub_ptr[0] != cur && strCompare(be_deleted, cur->second->key_in_trie, run_index, run_on_leaf) != Compare_Result::EQUAL)
return false;
}
delete cur->second;
delete cur->first;
cur->first = nullptr;
cur->second = nullptr;
--run->branch_ptr.num;
}
if (run != root && run->branch_ptr.num == 1)
{
const pair<vector<char>*, TrieTreeNode*>* temp = nullptr;
const vector<pair<vector<char>*, TrieTreeNode*>>& temp_r = run->branch_ptr.sub_ptr;
size_t r = 0;
for (const vector<pair<vector<char>*, TrieTreeNode*>>& temp_r = run->branch_ptr.sub_ptr; r != temp_r.size(); ++r)
{
if (temp_r[r].second != nullptr)
{
temp = &temp_r[r];
break;
}
}
if (temp->second->type_flag == TrieTreeNode::NodeType::BRANCHNODE)
{
if (father->first == nullptr)
father->first = new vector<char>(1, static_cast<char>(r));
else
father->first->push_back(static_cast<char>(r));
if (temp->first != nullptr)
{
father->first->insert(father->first->end(), temp->first->begin(), temp->first->end());
}
}
else
{
if (father->first != nullptr)
{
father->first->erase(father->first->begin(), father->first->end());
delete father->first;
father->first = nullptr;
}
}
father->second = temp->second;
delete run;
}
return true;
}
bool TrieTree::insert(const string& be_inserted) const
{
string::size_type run_index = 0;
TrieTreeNode* run = root;
pair<vector<char>*, TrieTreeNode*> *leaf_father = nullptr;
while (run->type_flag == TrieTreeNode::NodeType::BRANCHNODE)
{
if (run_index < be_inserted.size())
{
leaf_father = &run->branch_ptr.sub_ptr[char_to_index(be_inserted[run_index])];
if (leaf_father->second == nullptr)
{
leaf_father->second = new TrieTreeNode(be_inserted);
++run->branch_ptr.num;
return true;
}
++run_index;
run = leaf_father->second;
if (leaf_father->first != nullptr)
{
vector<char>::size_type run_on_prefix = 0;
Compare_Result compare_result = strCompare(be_inserted, *(leaf_father->first), run_index, run_on_prefix);
if (compare_result == Compare_Result::NOT_EQUAL || compare_result == Compare_Result::LEFT_IS_PREFIX)
{
leaf_father->second = new TrieTreeNode();
if (leaf_father->first->begin() + run_on_prefix + 1 == leaf_father->first->end())
leaf_father->second->branch_ptr.sub_ptr[char_to_index(*(leaf_father->first->begin() + run_on_prefix))].second = run;
else
leaf_father->second->branch_ptr.sub_ptr[char_to_index(*(leaf_father->first->begin() + run_on_prefix))] = make_pair(new vector<char>(leaf_father->first->begin() + run_on_prefix + 1, leaf_father->first->end()), run);
if (run_on_prefix == 0)
{
delete leaf_father->first;
leaf_father->first = nullptr;
}
else
leaf_father->first->erase(leaf_father->first->begin() + run_on_prefix, leaf_father->first->end());
if (compare_result == Compare_Result::NOT_EQUAL)
leaf_father->second->branch_ptr.sub_ptr[char_to_index(be_inserted[run_index])].second = new TrieTreeNode(be_inserted);
else
leaf_father->second->branch_ptr.sub_ptr[0].second = new TrieTreeNode(be_inserted);
leaf_father->second->branch_ptr.num = 2;
return true;
}
}
}
else
{
if (run->branch_ptr.sub_ptr[0].second == nullptr)
{
run->branch_ptr.sub_ptr[0].second = new TrieTreeNode(be_inserted);
++run->branch_ptr.num;
return true;
}
return false;
}
}
Compare_Result compare_result;
{
string::size_type start_index = run_index;
{
string::size_type run_on_str = run_index;
compare_result = strCompare(be_inserted, run->key_in_trie, run_index, run_on_str);
}
if (compare_result == Compare_Result::EQUAL)
return false;
leaf_father->second = new TrieTreeNode();
if (start_index != run_index) //
{
if (leaf_father->first == nullptr)
leaf_father->first = new vector<char>(be_inserted.begin() + start_index, be_inserted.begin() + run_index);
else
leaf_father->first->insert(leaf_father->first->end(), be_inserted.begin() + start_index, be_inserted.begin() + run_index);
}
}
if (compare_result == Compare_Result::LEFT_IS_PREFIX)
{
leaf_father->second->branch_ptr.sub_ptr[0].second = new TrieTreeNode(be_inserted);
leaf_father->second->branch_ptr.sub_ptr[char_to_index(run->key_in_trie[run_index])].second = run;
}
else if (compare_result == Compare_Result::RIGHT_IS_PREFIX)
{
leaf_father->second->branch_ptr.sub_ptr[0].second = run;
leaf_father->second->branch_ptr.sub_ptr[char_to_index(be_inserted[run_index])].second = new TrieTreeNode(be_inserted);
}
else
{
leaf_father->second->branch_ptr.sub_ptr[char_to_index(run->key_in_trie[run_index])].second = run;
leaf_father->second->branch_ptr.sub_ptr[char_to_index(be_inserted[run_index])].second = new TrieTreeNode(be_inserted);
}
leaf_father->second->branch_ptr.num = 2;
return true;
}
size_t find_next(TrieTreeNode* cur, size_t run)
{
for (; run < cur->branch_ptr.sub_ptr.size(); ++run)
{
if (cur->branch_ptr.sub_ptr[run].second != nullptr)
{
return run;
}
}
}
TrieTree::~TrieTree()
{
TrieTreeNode* run = root;
stack<tuple<TrieTreeNode*, size_t, short>> work_stack;
bool trace_back_flag = true;
while (true)
{
if (trace_back_flag == true)
{
if (run == root)
{
if (run->branch_ptr.num == 0)
{
delete root;
return;
}
}
else
{
if (run->type_flag == TrieTreeNode::DATANODE)
{
delete run;
run = get<0>(work_stack.top());
if (run->branch_ptr.num != get<2>(work_stack.top()))
get<1>(work_stack.top()) = find_next(run, get<1>(work_stack.top()) + 1);
trace_back_flag = false;
continue;
}
}
work_stack.push(make_tuple(run, find_next(run, 0), 1));
run = run->branch_ptr.sub_ptr[get<1>(work_stack.top())].second;
}
else
{
if (run == root || get<2>(work_stack.top()) != run->branch_ptr.num)
{
if (run == root)
{
if (get<2>(work_stack.top()) == root->branch_ptr.num)
{
delete root;
return;
}
}
++get<2>(work_stack.top());
run = run->branch_ptr.sub_ptr[get<1>(work_stack.top())].second;
trace_back_flag = true;
}
else
{
delete run;
work_stack.pop();
run = get<0>(work_stack.top());
if (run->branch_ptr.num != get<2>(work_stack.top()))
get<1>(work_stack.top()) = find_next(run, get<1>(work_stack.top()) + 1);
}
}
}
}
TrieTreeNode* TrieTree::copy()
{
TrieTreeNode* be_copied = root;
stack<tuple<TrieTreeNode*, size_t, short>> work_stack;
stack<TrieTreeNode*> copy_trace_stack;
TrieTreeNode* root_of_copy = nullptr;
bool trace_back_flag = true;
while (true)
{
if (trace_back_flag)
{
if (be_copied->type_flag == TrieTreeNode::BRANCHNODE)
{
if (be_copied == root)
{
root_of_copy = new TrieTreeNode(*be_copied);
if (be_copied->branch_ptr.num == 0)
{
break;
}
copy_trace_stack.push(root_of_copy);
}
else
copy_trace_stack.push(copy_trace_stack.top()->branch_ptr.sub_ptr[get<1>(work_stack.top())].second = new TrieTreeNode(*be_copied));
work_stack.push(make_tuple(be_copied, find_next(be_copied, 0), 1));
be_copied = be_copied->branch_ptr.sub_ptr[get<1>(work_stack.top())].second;
}
else
{
copy_trace_stack.top()->branch_ptr.sub_ptr[get<1>(work_stack.top())].second = new TrieTreeNode(*be_copied);
be_copied = get<0>(work_stack.top());
trace_back_flag = false;
}
}
else
{
if (be_copied->branch_ptr.num != get<2>(work_stack.top()))
{
get<1>(work_stack.top()) = find_next(be_copied, get<1>(work_stack.top()) + 1);
++get<2>(work_stack.top());
be_copied = be_copied->branch_ptr.sub_ptr[get<1>(work_stack.top())].second;
trace_back_flag = true;
}
else
{
if (be_copied == root)
break;
work_stack.pop();
be_copied = get<0>(work_stack.top());
copy_trace_stack.pop();
}
}
}
return root_of_copy;
}
void TrieTree::print(TrieTreeNode* cur, size_t level, size_t offset, vector<size_t> &height_to_length) const
{
if (cur->type_flag == TrieTreeNode::BRANCHNODE)
{
size_t M = height_to_length[level];
size_t temp_M;
int count = 0;
for (size_t run = 0; ; ++run)
{
if (cur->branch_ptr.sub_ptr[run].second != nullptr)
{
++count;
for (size_t go = 1; go <= offset; ++go)
cout << " ";
temp_M = M;
if (run == 0)
{
cout << "NULL";
temp_M -= 4;
}
else
{
cout << static_cast<char>(run);
temp_M -= 1;
}
if (cur->branch_ptr.sub_ptr[run].first != nullptr)
{
for (vector<char>::iterator go = cur->branch_ptr.sub_ptr[run].first->begin(); go != cur->branch_ptr.sub_ptr[run].first->end(); ++go)
cout << *go;
for (int i = 1; i <= temp_M - cur->branch_ptr.sub_ptr[run].first->size(); ++i)
cout << " ";
}
else
{
for (int i = 1; i <= temp_M; ++i)
cout << " ";
}
cout << "|-" << endl;
print(cur->branch_ptr.sub_ptr[run].second, level + 1, offset + 2 + M, height_to_length);
if (count == cur->branch_ptr.num)
break;
}
}
}
else
{
for (size_t go = 1; go <= offset; ++go)
cout << " ";
cout << "leaf:" << cur->key_in_trie << endl;
}
}
void TrieTree::printTrieTree(TrieTreeNode* root) const //放到运算符<<函数里调用
{
deque<TrieTreeNode*> work_queue;
vector<size_t> height_to_length;
work_queue.push_back(root);
while (work_queue.empty() == false)
{
size_t size = work_queue.size();
int max_length = 1;
for (size_t run = 1; run <= size; ++run)
{
TrieTreeNode* cur = work_queue.front();
work_queue.pop_front();
int count = 0;
if (cur->branch_ptr.sub_ptr[0].second != nullptr)
{
++count;
if (max_length < 4)
max_length = 4;
}
for (size_t go = 1; ; ++go)
{
if (cur->branch_ptr.sub_ptr[go].second != nullptr)
{
++count;
if (cur->branch_ptr.sub_ptr[go].second->type_flag == TrieTreeNode::NodeType::BRANCHNODE)
{
work_queue.push_back(cur->branch_ptr.sub_ptr[go].second);
if (cur->branch_ptr.sub_ptr[go].first != nullptr && max_length < cur->branch_ptr.sub_ptr[go].first->size() + 1)
max_length = cur->branch_ptr.sub_ptr[go].first->size() + 1;
}
if (count == cur->branch_ptr.num)
break;
}
}
}
height_to_length.push_back(max_length);
}
print(root, 0, 0, height_to_length);
}
void TrieTree::printTrieTree(TrieTreeNode* cur, size_t offset) const
{
if (cur->type_flag == TrieTreeNode::BRANCHNODE)
{
int count = 0;
int max_length = 1;
if (cur->branch_ptr.sub_ptr[0].second != nullptr)
{
++count;
max_length = 4;
}
for (size_t run = 1; ; ++run)
{
if (cur->branch_ptr.sub_ptr[run].second != nullptr)
{
++count;
if (cur->branch_ptr.sub_ptr[run].first != nullptr && max_length < cur->branch_ptr.sub_ptr[run].first->size() + 1)
max_length = cur->branch_ptr.sub_ptr[run].first->size() + 1;
if (count == cur->branch_ptr.num)
break;
}
}
int temp_length;
for (size_t run = 0; ; ++run)
{
if (cur->branch_ptr.sub_ptr[run].second != nullptr)
{
--count;
for (size_t go = 1; go <= offset; ++go)
cout << " ";
temp_length = max_length;
if (run == 0)
{
cout << "NULL";
temp_length -= 4;
}
else
{
cout << static_cast<char>(run);
temp_length -= 1;
}
if (cur->branch_ptr.sub_ptr[run].first != nullptr)
{
for (vector<char>::iterator go = cur->branch_ptr.sub_ptr[run].first->begin(); go != cur->branch_ptr.sub_ptr[run].first->end(); ++go)
cout << *go;
for (int i = 1; i <= temp_length - cur->branch_ptr.sub_ptr[run].first->size(); ++i)
cout << " ";
}
else
{
for (int i = 1; i <= temp_length; ++i)
cout << " ";
}
cout << "|-" << endl;
printTrieTree(cur->branch_ptr.sub_ptr[run].second, offset + 2 + max_length);
if (count == 0)
break;
}
}
}
else
{
for (size_t go = 1; go <= offset; ++go)
cout << " ";
cout << "leaf:" << cur->key_in_trie << endl;
}
}
int main()
{
vector<string> test = { "bluebird", "bunting", "bobwhite", "bluejay", "bl"/*, "a71Zwm", "a8KZX", "aNqMib3l", "aNty", "akBm1e9", "anm", "as"*/};
TrieTree test_obj;
for (vector<string>::iterator p = test.begin(); p != test.end(); ++p)
{
cout << "插入字符串" << *p << endl;
if (test_obj.insert(*p))
{
cout << "插入成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy <<endl;
}
else
{
cout << "插入失败" << endl;
exit(0);
}
}
cout << endl;
//for (vector<string>::iterator p = test.begin(); p != test.end(); ++p)
{
cout << "删除字符串" << "bobwhite" << endl;
if (test_obj.deleteElem("bobwhite"))
{
cout << "删除成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "删除失败" << endl;
exit(0);
}
cout << "删除字符串" << "bunting" << endl;
if (test_obj.deleteElem("bunting"))
{
cout << "删除成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "删除失败" << endl;
exit(0);
}
}
cout << endl;
/*string mod = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
const int L = 9; // 随机字符串最大长度
const int r = 2; //相同长度重复次数
vector<int> LList(L);
vector<string> random_str;
for (int run = 0; run < LList.size(); ++run)
LList[run] = run + 1;
shuffle(LList.begin(), LList.end(), default_random_engine());
for (int re = 1; re <= r; ++re)
{
for (int run = 0; run < LList.size(); ++run)
{
string r;
for (int go = 1; go <= LList[run]; ++go)
{
r.append(1, mod[rand() % mod.size()]);
}
random_str.push_back(r);
}
}
for (vector<string>::iterator p = random_str.begin(); p != random_str.end(); ++p)
{
cout << "插入字符串" << *p << endl;
if (test_obj.insert(*p))
{
cout << "插入成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "插入失败" << endl;
exit(0);
}
}
cout << endl;
// TrieTreeNode *copy = test_ptr.copy();
for (vector<string>::iterator p = random_str.begin(); p != random_str.end(); ++p)
{
cout << "删除字符串" << *p << endl;
if (test_obj.deleteElem(*p))
{
cout << "删除成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "删除失败" << endl;
exit(0);
}
}
cout << endl;
random_str.clear();
for (int i = 1; i <= 7; ++i)
{
string temp(mod, 0, i);
for (int run = 1; run <= 7; ++run)
{
string r;
for (int go = 1; go <= run; ++go)
{
r.append(1, mod[rand() % mod.size()]);
}
random_str.push_back(temp + r);
}
}
cout << "测试字符串有共同前缀不相等情形" << endl;
for (vector<string>::iterator p = random_str.begin(); p != random_str.end(); ++p)
{
cout << "插入字符串" << *p << endl;
if (test_obj.insert(*p))
{
cout << "插入成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "插入失败" << endl;
exit(0);
}
}
cout << endl;
// TrieTreeNode *copy = test_ptr.copy();
for (vector<string>::iterator p = random_str.begin(); p != random_str.end(); ++p)
{
cout << "删除字符串" << *p << endl;
if (test_obj.deleteElem(*p))
{
cout << "删除成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "删除失败" << endl;
exit(0);
}
}
cout << endl;
shuffle(mod.begin(), mod.end(), default_random_engine());
for (string::size_type i = 1; i <= mod.size(); ++i)
{
string temp(mod, 0, i);
cout << "插入字符串" << mod << "的前缀" << temp << endl;
if (test_obj.insert(temp))
{
cout << "插入成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "插入失败" << endl;
exit(0);
}
}
for (string::size_type i = 1; i <= mod.size(); ++i)
{
string temp(mod, 0, i);
cout << "删除字符串" << mod << "的前缀" << temp << endl;
if (test_obj.deleteElem(temp))
{
cout << "删除成功" << endl;
cout << "当前Trie为:" << endl << test_obj << endl;
TrieTree copy(test_obj);
cout << "当前Trie的副本为:" << endl << copy << endl;
}
else
{
cout << "删除失败" << endl;
exit(0);
}
}*/
return 0;
}
2842

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



