Fortune left-law basis class7- 1 title prefix tree a range of issues

1. Title: prefix tree a range of issues

Generating a prefix tree, including adding, deleting, function lookup, also need to find a prefix number that appears.

2. prefix tree

(1) Introduction prefix tree

Prefix tree for statistical word frequency, as shown below when we add "abc", "abd", "bce", "be", will get the following tree when "bef". Wherein the root node is not stored characters, only play the role of position marks, in order to store the 26 letters, each node 26 may store path implied az characters, adding the node before the road is displayed as a character store, then this difference can be seen that the general tree and tree, each node has at most 26 child node; if stored as "abc", "abd" Thus, the same location of different string "ab" is the same, using the same node.

Here Insert Picture Description
In order to increase functionality prefix tree, we add two variables path and end initialized to 0 on the node. end a good understanding of what is recorded at the end of the place, so if a node end is not 0, then the node will terminate node. Below "bef" at the end of the e 1, f is 1, so that the storage can be obtained is too "be", and "bef"; path variable is acting, after this node times, its use is record the number of strings using this prefix. For example, "abc", "abd", this path is 2 at a chain, the prefix indicates the entire tree is stored in such "a" has two. The following diagram represents the end red and blue values ​​and path of a node.

Here Insert Picture Description

(2) implementation class prefix tree

① node class

For each node, we need to record the end, path two variables, in addition to the need to use an array to represent 26 road leading to the child node of the node. Initialization, path, end is 0, using memset function array 26 is also set to zero.

#define num 26

class TrieNode
{
public:
	int path;	//经过的次数
	int end;	//结束的次数
	TrieNode* nexts[num];

	//构造
	TrieNode():path(0),end(0)
	{ //memset(结构体/数组名,用于替换的ASCII码对应字符,前n个字符 );
		memset(nexts,0,sizeof(nexts));
	}

};

② tree class

The root node using the class definition.

class TrieTree
{
private:
	TrieNode *root;
public:
    TrieTree();
    ~TrieTree();
    //成员函数
	void destory(TrieNode *node);
	void insert(string word);
	int research(string word);
	void delete_word(string word);
	int prefixNumber(string pre);
};
//构造
TrieTree::TrieTree()
{
	root = new TrieNod();
}
//析构
TrieTree::~TrieTree()
{
	destory(root);
}	
//删除
void TrieTree::destory(TrieNode *root)
{
	if(root ==NULL)
		return;
	for(int i = 0; i < num; i++)
	{	//每个new出的数组需要删除
		destory(root->nexts[i]);
	}
	delete root;
	root = NULL;
}

3. member function

(1) Add Function

The whole idea: If you insert the string is empty, return directly; inserting the string into an array of characters stored for the entire array traversal, if the road leading to a character does not currently exist, a new one, then the path ++, and finally the end ++

void TrieTree::insert(string word)
{
	if(word == "")								//插入字符串为空
		return;
	char *buf = new char[word.size()];			//开辟字符串长度的数组
	strcpy(buf,word.c_str());					//转换为c的char字符串
	TrieNode *node = root;
	int index = 0;
	for(int i = 0;i < strlen(buf); i++)
	{
		index = buf[i] - 'a';					//将输入的字符转换为索引值a是0,b是1...
		if(node->nexts[index] == NULL)			//这条路未被创建
		{
			node->nexts[index] = new TrieNode();//创建路
		}
		node = node->nexts[index];				//指向新建的路
		node->path++;							//经过+1
	}
	node->end++;								//最后再记录结束
	

(2) Find function

And add basic function is similar, except that when traversing less than if the road to find a character, there is no return, if each can be found, return to the end of the recording end.

int TrieTree::research(string word)
{
	if(word == "")
		return 0;
	char *buf = new char[word.size()];
	//char *strcpy(char* dest, const char *src)
	//string类对象的成员函数c_str()把string 对象转换成c中的字符串
	strcpy(buf,word.c_str());
	int index = 0;
	TrieNode *node = root;
	for(int i = 0;i < strlen(buf);i++)
	{
		index = buf[i] - 'a';
		if(NULL == node->nexts[index])
			return 0;
		node = node->nexts[index];
	}
	return node->end;
}

(3) Delete function

Delete process to find, if there is no exit. When present, each array traversal path passing minus one, if the path described becomes 0, note that only one strand need to remove the tree, a node position intermediate variables need to record deleted.

void TrieTree::delete_word(string word)
{
	if(research(word) == 0)		//先进行查找确定存在
		return;
	TrieNode *node = root;
	TrieNode *tmp = root;
	int index = 0;
	char *buf = new char[word.size()];
	strcpy(buf,word.c_str());
	for(int i = 0;i < strlen(buf);i++)
	{
		index = buf[i] - 'a';
		tmp = node->nexts[index];			//使用中间变量记录当前节点的下一个节点
		if(--node->nexts[index]->path == 0)	//如果将--path后,节点的path为0,表示以后的节点都不存在
			delete node->nexts[index];		//释放
		node = tmp;							//当前节点移动到下一个节点
	}
	node->end--;
}

(4) Find the number of occurrences of a prefix

Prefix can not be lookup function to find, because the end is not present on the prefix, it is necessary to traverse the array is determined, if the traversing node is 0, indicates the absence of this prefix, directly returns 0 exit, are present after traversing the return path represented through the number of nodes is the number of times a prefix.

int TrieTree::prefixNumber(string pre) 
{
	if(pre == "")
		return 0;
	char *buf = new char[pre.size()];
	strcpy(buf,pre.c_str());

	TrieNode * node = root;
	int index = 0;
	for(int i = 0;i < strlen(buf);i++)
	{
		index = buf[i] - 'a';
		if(node->nexts[index] == NULL)	//不存在此前缀直接返回0个
			return 0;
		node = node->nexts[index];		
	}
	return node->path;
}

4. The complete code

#include<iostream>
#include<string>
using namespace std;
#define num 26

class TrieNode
{
public:
	int path;	//经过的次数
	int end;	//结尾的次数
	TrieNode* nexts[num];

	//构造
	TrieNode():path(0),end(0)
	{ //memset(结构体/数组名,用于替换的ASCII码对应字符,前n个字符 );
		memset(nexts,0,sizeof(nexts));
	}
	
};

class TrieTree
{
private:
	TrieNode *root;
public:
    TrieTree();
    ~TrieTree();
	void destory(TrieNode *node);
	void insert(string word);
	int research(string word);
	void delete_word(string word);
	int prefixNumber(string pre);
};

//构造
TrieTree::TrieTree()
{
	root = new TrieNode();
}
//析构
TrieTree::~TrieTree()
{
	destory(root);
}	
//删除
void TrieTree::destory(TrieNode *root)
{
	if(root ==NULL)
		return;
	for(int i = 0; i < num; i++)
	{	//每个new出的数组需要删除
		destory(root->nexts[i]);
	}
	delete root;
	root = NULL;
}
//添加函数
void TrieTree::insert(string word)
{
	if(word == "")								//插入字符串为空
		return;
	char *buf = new char[word.size()];			//开辟字符串长度的数组
	strcpy(buf,word.c_str());					//转换为c的char字符串
	TrieNode *node = root;
	int index = 0;
	for(int i = 0;i < strlen(buf); i++)
	{
		index = buf[i] - 'a';					//将输入的字符转换为索引值a是0,b是1...
		if(node->nexts[index] == NULL)			//这条路未被创建
		{
			node->nexts[index] = new TrieNode();//创建路
		}
		node = node->nexts[index];				//指向新建的路
		node->path++;							//经过+1
	}
	node->end++;								//最后再记录结束
	
}

//查找函数
int TrieTree::research(string word)
{
	if(word == "")
		return 0;
	char *buf = new char[word.size()];
	//char *strcpy(char* dest, const char *src)
	//string类对象的成员函数c_str()把string 对象转换成c中的字符串
	strcpy(buf,word.c_str());
	int index = 0;
	TrieNode *node = root;
	for(int i = 0;i < strlen(buf);i++)
	{
		index = buf[i] - 'a';
		if(NULL == node->nexts[index])
			return 0;
		node = node->nexts[index];
	}
	return node->end;
}
//删除函数
void TrieTree::delete_word(string word)
{
	if(research(word) == 0)		//先进行查找确定存在
		return;
	TrieNode *node = root;
	TrieNode *tmp = root;
	int index = 0;
	char *buf = new char[word.size()];
	strcpy(buf,word.c_str());
	for(int i = 0;i < strlen(buf);i++)
	{
		index = buf[i] - 'a';
		tmp = node->nexts[index];			//使用中间变量记录当前节点的下一个节点
		if(--node->nexts[index]->path == 0)	//如果将--path后,节点的path为0,表示以后的节点都不存在
			delete node->nexts[index];		//释放
		node = tmp;							//当前节点移动到下一个节点
	}
	node->end--;
}
//查找某前缀次数函数
int TrieTree::prefixNumber(string pre) 
{
	if(pre == "")
		return 0;
	char *buf = new char[pre.size()];
	strcpy(buf,pre.c_str());

	TrieNode * node = root;
	int index = 0;
	for(int i = 0;i < strlen(buf);i++)
	{
		index = buf[i] - 'a';
		if(node->nexts[index] == NULL)	//不存在此前缀直接返回0个
			return 0;
		node = node->nexts[index];		
	}
	return node->path;
}


int main()
{
	//////string str = "aaaaa";
	////////vector<char> b(str.size());
	//////char *buf = new char[str.size()];
	//////strcpy(buf, str.c_str());
	TrieTree a;
	a.insert("abdd");
	a.insert("abc");
	a.insert("abcd");
	a.research("abdd");
	a.delete_word("abc");
	a.insert("abd");
	cout<<a.prefixNumber("abcd")<<endl;

	return 0;
}

Published 51 original articles · won praise 1 · views 1366

Guess you like

Origin blog.csdn.net/shi_xiao_xuan/article/details/104251651