Trie树标准模版
Posted FFjet
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Trie树标准模版相关的知识,希望对你有一定的参考价值。
这是一个Trie树标准模版
By Leo
本人版权,请勿抄袭!!
先看教程:
1. 什么是trie树
1.Trie树 (特例结构树)
2. 三个基本特性:
3 .例子
和二叉查找树不同,在trie树中,每个结点上并非存储一个元素。trie树把要查找的关键词看作一个字符序列。并根据构成关键词字符的先后顺序构造用于检索的树结构。
在trie树上进行检索类似于查阅英语词典。
例如,电子英文词典,为了方便用户快速检索英语单词,可以建立一棵trie树。例如词典由下面的单词成:a、b、c、aa、ab、ac、ba、ca、aba、abc、baa、bab、bac、cab、abba、baba、caba、abaca、caaba
再举一个例子。给出一组单词,inn, int, at, age, adv, ant, 我们可以得到下面的Trie:
可以看出:
- 每条边对应一个字母。
- 每个节点对应一项前缀。叶节点对应最长前缀,即单词本身。
- 单词inn与单词int有共同的前缀“in”, 因此他们共享左边的一条分支,root->i->in。同理,ate, age, adv, 和ant共享前缀"a",所以他们共享从根节点到节点"a"的边。
查询操纵非常简单。比如要查找int,顺着路径i -> in -> int就找到了。
1.插入过程
对于一个单词,从根开始,沿着单词的各个字母所对应的树中的节点分支向下走,直到单词遍历完,将最后的节点标记为红色,表示该单词已插入trie树。
2. 查找过程
其方法为:
(1) 从根结点开始一次搜索;
(2) 取得要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;
即从根开始按照单词的字母顺序向下遍历trie树,一旦发现某个节点标记不存在或者单词遍历完成而最后的节点未标记为红色,则表示该单词不存在,若最后的节点标记为红色,表示该单词存在。如下图中:trie树中存在的就是abc、d、da、dda四个单词。在实际的问题中可以将标记颜色的标志位改为数量count等其他符合题目要求的变量。
代码上有英文注释,请还是不懂的人看一看。。
再看不懂,本人也无能为力了~~~
代码:
/** * Leolee 2017(C) * Trie.cpp * This is a standard Trie‘s template by Leolee * The program has its copyright and you cannot copy it * before the author allowed. */ //Define the TRIE Template here #ifndef _TRIE_ #define _TRIE_ #include <iostream> //The standard IO stream #include <sstream> //The standard String library and string stream #include <cstring> //The C-style string library #include <cassert> //The C-style assert library #include <climits> //For using "INT_MIN" #define MAXNUM 26 //The max num of the children of a node using namespace std; //using the standard namespace "std" //define the Trie node here struct Trie_Node { string word;//The word int count; //The number of occurrences of a word Trie_Node *Next_Branch[MAXNUM];//Pointer to a 26-character node Trie_Node() : count(0) { word.empty(); memset(Next_Branch, NULL, sizeof(Trie_Node*) * MAXNUM); } ~Trie_Node() {}; }; class Trie { private: Trie_Node* ROOT; private: void Reset(Trie_Node* Root); //Reset The trie tree void Print(Trie_Node* Root); public: void Insert(string str); //Insert the string str bool Search(string str, int& cnt); //Find the string str and return the number of occurrences bool Remove(string str); //Delete the string str void PrintALL(); //Prints all the nodes in the trie tree bool PrintPre(string str); //Print a word prefixed with str Trie() { ROOT = new Trie_Node(); //Note that the root of the dictionary tree does not hold characters }; ~Trie() { Reset(ROOT); }; }; #endif //_TRIE_ //Insert a word void Trie::Insert(string str) { if (str.empty()) return; Trie_Node *NODE = ROOT; int len = str.size(); for (int i = 0;i < len;i++) { int index = str.at(i) - ‘a‘; //Case sensitive if (index < 0 || index > MAXNUM)//No insertion is performed return; if (NODE->Next_Branch[index] == NULL) //The prefix of the word does not exist and is to be generated for that node NODE->Next_Branch[index] = new Trie_Node(); NODE = NODE->Next_Branch[index]; //Go to the next node } if (!NODE->word.empty()) //The word has already appeared { NODE->count++; return; } else //The word did not appear, and we should insert it { NODE->count++; NODE->word = str; } } //Find a word, if it appeared, then return the number of occurrences of the word. //If not, it will return false bool Trie::Search(string str, int& cnt) { assert(!str.empty()); int index = INT_MIN; Trie_Node *NODE = ROOT; int length = str.size(); int i = 0; while (NODE && i < length) { index = str.at(i) - ‘a‘; //Case sensitive if (index < 0 || index > MAXNUM) //No insertion is performed return false; NODE = NODE->Next_Branch[index]; i++; } if (NODE && !NODE->word.empty()) { cnt = NODE->count; return true; } return false; } bool Trie::Remove(string str) { assert(!str.empty()); int index = INT_MIN; Trie_Node *NODE = ROOT; int length = str.size(); int i = 0; while (NODE && i < length) { index = str.at(i) - ‘a‘; //Case sensitive if (index < 0 || index > MAXNUM) //No deletion is performed return false; NODE = NODE->Next_Branch[index]; i++; } if (NODE && !NODE->word.empty()) { NODE->word.clear(); return true; } } void Trie::PrintALL() { Print(ROOT); } bool Trie::PrintPre(string str) { assert(!str.empty()); int index = INT_MIN; Trie_Node *NODE = ROOT; int length = str.size(); int i = 0; while (NODE && i < length) { index = str.at(i) - ‘a‘; //Case sensitive if (index < 0 || index > MAXNUM) return false; NODE = NODE->Next_Branch[index]; i++; } if (NODE) //We can find the word { Print(NODE); return true; } return false; } void Trie::Print(Trie_Node* Root) { if (Root == NULL) return; //Print the word if (!Root->word.empty()) cout << Root->word << " " << Root->count << endl; for (int i = 0;i < MAXNUM;i++) Print(Root->Next_Branch[i]);//Print all the children of the node } //Rest trie tree void Trie::Reset(Trie_Node* Root) { if (Root == NULL) return; for (int i = 0;i < MAXNUM;i++) Reset(Root->Next_Branch[i]); //Reset the word if (!Root->word.empty()) Root->word.clear(); delete Root; //Delete the node Root = NULL; } int NUM_TO_INSERT, NUM_TO_SEARCH, NUM_TO_DELETE, NUM_TO_SBF; //Main Function int main(int argc, char **argv) { ios::sync_with_stdio(false); Trie TREE; cout << "Input the number of words you want to insert:" << endl; cin >> NUM_TO_INSERT; for (int i = 0;i < NUM_TO_INSERT;i++) { string STRING; cin >> STRING; TREE.Insert(STRING); } cout << endl; cout << "Input the number of words you want to search:" << endl; cin >> NUM_TO_SEARCH; for (int i = 0;i < NUM_TO_SEARCH;i++) { string STRING; cin >> STRING; int count = -1; bool CanFind = TREE.Search(STRING, count); if (CanFind) cout << STRING << " exists, its number of occurrences is " << count << endl; else cout << STRING << " does not exists!" << endl; } cout << endl; cout << "Here are all the nodes in the Trie tree:" << endl; TREE.PrintALL(); cout << endl; cout << "Input the number of words you want to delete:" << endl; cin >> NUM_TO_DELETE; for (int i = 0;i < NUM_TO_DELETE;i++) { string STRING; cin >> STRING; bool Is_Deleted = TREE.Remove(STRING); if (Is_Deleted) cout << STRING << " deleted!" << endl; else cout << "Failed to delete " << STRING << endl; } cout << endl; cout << "Input the number of words you want to search by prefix:" << endl; cin >> NUM_TO_SBF; for (int i = 0;i < NUM_TO_SBF;i++) { string STRING; cin >> STRING; bool STATUS = TREE.PrintPre(STRING); if (!STATUS) cout << "There aren‘t any words begin with " << STRING << " !"; cout << endl; } cout << endl; return 0; }
以上是关于Trie树标准模版的主要内容,如果未能解决你的问题,请参考以下文章