Trie树标准模版

/**
  *			  FFjet 2017(C)
  *				Trie.cpp
  * This is a standard Trie's template by FFjet
  * 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;
}

  

posted @ 2017-01-25 16:57  FFjet  阅读(635)  评论(0)    收藏  举报