Fortuna base a la ley dada class7- 1 título prefijo árbol de una serie de cuestiones

1. Título: prefijo de árbol de una serie de cuestiones

Generación de un árbol de prefijo, incluyendo la adición, eliminación de búsqueda función, también es necesario encontrar un número de prefijo que aparece.

2. árbol de prefijo

árbol prefijo (1) Introducción

árbol de prefijo para la frecuencia de palabras estadística, como se muestra a continuación cuando añadimos "abc", "abd", "AC", "ser", obtendrá el siguiente árbol cuando "BEF". En el que el nodo raíz no se almacena caracteres, sólo juegan el papel de las marcas de posición, con el fin de almacenar las 26 letras, cada nodo 26 puede almacenar trayectoria implícita az personajes, añadiendo el nodo antes de que la carretera se muestra como una tienda de personajes, a continuación, esta diferencia se puede ver que el árbol general y árbol, cada nodo tiene como máximo 26 nodo hijo; si se almacena como "abc", "abd" por lo tanto, la misma ubicación de cadena diferente "ab" es el mismo, usando el mismo nodo.

Aquí Insertar imagen Descripción
Con el fin de aumentar la funcionalidad del árbol de prefijo, añadimos ruta dos variables y al final inicializado a 0 en el nodo. poner fin a una buena comprensión de lo que se registra en el extremo del lugar, por lo que si un nodo final no es 0, entonces el nodo terminará nodo. A continuación "bef" al final de la dirección 1, f es 1, por lo que el almacenamiento se puede obtener es demasiado "ser", y "bef"; variable de ruta está actuando, después de estos tiempos de nodo, su uso es registrar el número de cadenas que utilizan este prefijo. Por ejemplo, "abc", "abd", este camino es 2 en una cadena, el prefijo indica el árbol entero se almacena en tales "a" tiene dos. El siguiente diagrama representa el rojo extremo y los valores de color azul y la ruta de un nodo.

Aquí Insertar imagen Descripción

árbol de prefijo de clase (2) aplicación

① clase nodo

Para cada nodo, necesitamos registrar los finales, el recorrido de dos variables, además de la necesidad de utilizar una matriz para representar a 26 camino que conduce al nodo hijo del nodo. Inicialización, trayectoria, final es 0, usando array función memset 26 también se establece en cero.

#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));
	}

};

② árbol de la clase

El nodo raíz mediante la definición de clase.

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. función miembro

(1) Función Agregar

La idea: Si inserta la cadena está vacía, volver directamente; la inserción de la cadena en una matriz de caracteres almacenados durante todo el recorrido de la matriz, si el camino que conduce a un personaje no existe en la actualidad, uno nuevo, entonces el camino ++, y, finalmente, al final ++

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) función Buscar

Y añadir la función básica es similar, excepto que cuando se atraviesa menor que si el camino para encontrar un personaje, no hay retorno, si cada uno se puede encontrar, regreso al final de la finalización de la grabación.

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) función Borrar

proceso de eliminación de encontrar, si no hay salida. Cuando está presente, cada trayectoria de matriz de recorrido que pasa menos uno, si la ruta descrita se convierte en 0, nota que sólo una necesidad hebra para quitar el árbol, una posición de nodo variables intermedias necesitan registro eliminado.

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) Encontrar el número de ocurrencias de un prefijo

Prefijo no puede ser de búsqueda de la función de encontrar, ya que el extremo no está presente en el prefijo, es necesario atravesar la matriz se determina, si el nodo de desplazamiento es 0, indica la ausencia de este prefijo, devuelve directamente 0 salida, están presentes después de atravesar la ruta de retorno representados a través el número de nodos es el número de veces que un prefijo.

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. El código completo

#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;
}

Publicado 51 artículos originales · ganado elogios 1 · vistas 1366

Supongo que te gusta

Origin blog.csdn.net/shi_xiao_xuan/article/details/104251651
Recomendado
Clasificación