Estructura de datos-----árbol de clasificación binaria

Tabla de contenido

Prefacio

1.¿Qué es un árbol de clasificación binario?

2. Cómo construir un árbol de clasificación binario

3. Operación del árbol de clasificación binaria.

3.1 Definir el método de almacenamiento de nodos

3.2 Operación de inserción de nodo

3.2 Crear un árbol de clasificación binario

3.4 Salida transversal (recorrido en orden)

3.5 Operación de búsqueda de datos

3.6 Obtener los valores máximo y mínimo

3.7 Eliminar operación de nodo

3.8 Destruir el árbol de clasificación binario

4. Código completo


Prefacio

        Hoy continuamos aprendiendo nuevos puntos de conocimiento: ordenar árboles binarios. Antes de eso, aprendimos algoritmos de clasificación relacionados. Le damos una matriz y luego la ordenamos. Luego, de la misma manera, también podemos construir un árbol de clasificación binario y ordenarlo durante el proceso de creación del árbol. El efecto de clasificación también se puede lograr. ¡Echemos un vistazo a continuación!

1.¿Qué es un árbol de clasificación binario?

        Árbol de clasificación binaria, también conocido como árbol de búsqueda binaria, también conocido como árbol de búsqueda binaria . Es un tipo de estructura de datos . En general, la eficiencia de la consulta es mayor  que la estructura de lista vinculada .

Dado un árbol binario, si se cumplen las siguientes condiciones, es un árbol binario ordenado

  • Si su subárbol izquierdo no está vacío, los valores de todos los nodos en el subárbol izquierdo son menores que el valor de su nodo raíz.
  • Si su subárbol derecho no está vacío, entonces los valores de todos los nodos en el subárbol derecho son mayores que el valor de su nodo raíz.
  • Sus subárboles izquierdo y derecho son árboles de clasificación binarios.

La mayor ventaja de un árbol de clasificación binario es su alta eficiencia de búsqueda. En comparación con la búsqueda uno por uno en una lista vinculada, un árbol de clasificación binario puede buscar de acuerdo con las reglas de clasificación de los datos.

Diagrama de árbol de clasificación binaria:

2. Cómo construir un árbol de clasificación binario

Por ejemplo, dada una matriz [62,88,58,47,35,73,51,99,37,93]  , primero obtenga el primer número, use este número como nodo raíz (estándar) y constrúyalo. Si el número es mayor que este, se coloca en el subárbol derecho, y si es menor que esto, se coloca en el subárbol izquierdo, como se muestra en la siguiente figura:

 Aquí podemos ver que estos nodos se insertan uno por uno, luego podemos crearlos mediante inserción recursiva, recorrerlos hacia abajo en orden, encontrar la posición adecuada y luego realizar la operación de inserción.

3. Operación del árbol de clasificación binaria.

3.1 Definir el método de almacenamiento de nodos

#include<stdio.h>
#include<stdlib.h>

//二叉排序树节点存储方式
typedef int DataType;
typedef struct binarytreenode {
	DataType data;	//数据域
	struct binarytreenode* left;	//左指针 
	struct binarytreenode* right;	//右指针
}BTnode;

3.2 Operación de inserción de nodo

Para insertar un nodo, primero se debe buscar la posición donde se debe insertar el nodo, comenzando desde el siguiente nodo, si es más pequeño que el siguiente, vaya hacia la izquierda, si es más grande, vaya hacia la derecha, hasta que Se inserta la posición del nodo hoja.

Código: 

//插入数据
void Insert_node(BTnode** root, DataType data) {
	if (*root == NULL) {
		*root = (BTnode*)malloc(sizeof(BTnode));
		if (!*root) {
			printf("ERROR\n");
			exit(-1);
		}
		(*root)->data = data;
		(*root)->left = NULL;
		(*root)->right = NULL;
	}

	else if ((*root)->data <= data)
		Insert_node(&(*root)->right, data);
	else if ((*root)->data > data)
		Insert_node(&(*root)->left, data);
}

3.2 Crear un árbol de clasificación binario

Para crear un árbol ordenado binario, solo necesita insertar los nodos uno por uno y finalmente devolver el nodo raíz. El código se muestra a continuación:

//创建排序二叉树
BTnode* Create_sortBtree(DataType* arr, int size) {
	if (!arr)
		return NULL;
	else {
		BTnode* T = NULL;
		for (int i = 0; i < size; i++) {
			Insert_node(&T, arr[i]);
		}
		return T;
	}
}

3.4 Salida transversal (recorrido en orden)

//中序遍历排序二叉树
void mid_travel(BTnode* T)
{
	if (!T)
		return;
	mid_travel(T->left);
	printf("%d ", T->data);
	mid_travel(T->right);
}

3.5 Operación de búsqueda de datos

La operación de buscar un determinado nodo de valor en un árbol ordenado binario y luego devolver este nodo. Esto se puede lograr mediante dos métodos: recursivo y no recursivo, el código es el siguiente:

Implementación recursiva: 

BTnode* Btree_search(BTnode* root, DataType target) {
	if (!root)
		return NULL;
	if (target == root->data) {
		return root;
	}
	return target > root->data ? Btree_search(root->right, target) : Btree_search(root->left, target);
}

 Implementación no recursiva (implementación iterativa):

//非递归查找
BTnode* Btree_search_fa(BTnode* T, DataType target) {
	BTnode* p = T;
	while (p) {
		if (p->data == target)
		{
			return p;
		}
		p = target > p->data ? p->right : p->left;
	}
	return NULL;
}

3.6 Obtener los valores máximo y mínimo

Para obtener el valor máximo o mínimo en un árbol binario ordenado, para decirlo sin rodeos, simplemente busque los nodos más a la derecha y más a la izquierda. Los dos valores máximos del árbol binario ordenado están en los dos lados extremos. El código se muestra a continuación:

Obtener el valor máximo

//获取最大值
int Btree_max(BTnode* T) {
	BTnode* cur = T;
	while (cur->right) {
		cur = cur->right;
	}
	return cur->data;
}

 Obtener el valor mínimo

//获取最小值
int Btree_min(BTnode* T) {
	BTnode* cur = T;
	while (cur->left) {
		cur = cur->left;
	}
	return cur->data;
}

3.7 Eliminar operación de nodo

Eliminar un nodo puede dañar la estructura del árbol binario ordenado, por lo que es necesario solucionarlo en varios casos. 1. Si elimina un nodo hoja, puede eliminarlo directamente, porque los nodos izquierdo y derecho del nodo hoja están vacíos, lo que no afectará la estructura del árbol de clasificación binario; 2. Si el nodo que se va a eliminar solo tiene un subárbol izquierdo o si hay un subárbol derecho, solo necesitamos encontrar el nodo izquierdo o el nodo derecho del nodo y luego reemplazar el nodo que se eliminará; 3. Si el nodo que se eliminará tiene subárboles izquierdo y derecho, aquí lo haremos Es necesario atravesar para encontrar un nodo que sea un bit más grande o un bit más pequeño que este nodo para reemplazar este nodo. Como se muestra abajo:

1. Eliminar nodos hoja 

 2. Eliminar nodos con un solo subárbol izquierdo (derecho)

3. Eliminar nodos con subárboles izquierdo y derecho. 

Código:

//删除节点
void Btree_del(BTnode* T, DataType l) {
	if (!T) {
		printf("fuck no\n");
		return;
	}
	//找到这个要删除节点的父节点
	BTnode* p = T, * f = NULL;
	while (p) {
		if (p->data == l)
		{
			break;
		}
		f = p;
		p = l > p->data ? p->right : p->left;
	}
	if (!p)
	{
		printf("没有这个节点\n");
		return;
	}
	BTnode* target = p;//此时的要删除目标节点
	BTnode* par = f; //此时要删除节点的父节点

	//第一种情况 此节点只有一个子树的时候
	if (!target->left && target->right != NULL)
	{
		if (target->data > par->data) {
			par->right = target->right;
		}
		else {
			par->left = target->right;
		}
		free(target);//释放空间
		target = NULL;
	}
	else if (target->left != NULL && !target->right) {
		if (target->data > par->data) {
			par->right = target->left;
		}
		else {
			par->left = target->left;
		}
		free(target);
		target = NULL;
	}
	//第二种情况,如果删除的是叶节点,直接删除即可
	else if (!target->left && !target->right) {
		if (target->data > par->data) {
			par->right = NULL;
		}
		else {
			par->left = NULL;
		}
		free(target);
		target = NULL;
	}
	//第三种情况,如果左右子树都存在的话
	//可以用右子树的最小元素
	//或者左子树的最大元素来替代被删除的节点
	//我这里就直接去用左树的最大代替这个节点
	else
	{
		BTnode* Lchild = target->left;
		while (Lchild->right != NULL) {
			Lchild = Lchild->right;
		}
		if (target->data > par->data) {
			par->right = Lchild;
		}
		else {
			par->left = Lchild;
		}
		free(target);
		target = NULL;
	}
	printf("Deleting successfully\n");
}

3.8 Destruir el árbol de clasificación binario

//销毁
void Destory_btree(BTnode* T) {
	if (!T)
		return;
	BTnode* cur = T;
	if (cur->left)
		Destory_btree(cur->left);
	if (cur->right)
		Destory_btree(cur->right);
	free(T);
}

4. Código completo

#include<stdio.h>
#include<stdlib.h>

//二叉排序树节点存储方式
typedef int DataType;
typedef struct binarytreenode {
	DataType data;	//数据域
	struct binarytreenode* left;	//左指针 
	struct binarytreenode* right;	//右指针
}BTnode;


//插入数据
void Insert_node(BTnode** root, DataType data) {
	if (*root == NULL) {
		*root = (BTnode*)malloc(sizeof(BTnode));
		if (!*root) {
			printf("ERROR\n");
			exit(-1);
		}
		(*root)->data = data;
		(*root)->left = NULL;
		(*root)->right = NULL;
	}

	else if ((*root)->data <= data)
		Insert_node(&(*root)->right, data);
	else if ((*root)->data > data)
		Insert_node(&(*root)->left, data);
}


//创建排序二叉树
BTnode* Create_sortBtree(DataType* arr, int size) {
	if (!arr)
		return NULL;
	else {
		BTnode* T = NULL;
		for (int i = 0; i < size; i++) {
			Insert_node(&T, arr[i]);
		}
		return T;
	}
}

//中序遍历排序二叉树
void mid_travel(BTnode* T)
{
	if (!T)
		return;
	mid_travel(T->left);
	printf("%d ", T->data);
	mid_travel(T->right);
}

//递归查找数据
BTnode* Btree_search(BTnode* root, DataType target) {
	if (!root)
		return NULL;
	if (target == root->data) {
		return root;
	}
	return target > root->data ? Btree_search(root->right, target) : Btree_search(root->left, target);
}
//非递归查找
BTnode* Btree_search_fa(BTnode* T, DataType target) {
	BTnode* p = T, * f = NULL;
	while (p) {
		if (p->data == target)
		{
			return f;
		}
		f = p;
		p = target > p->data ? p->right : p->left;
	}
	return NULL;
}

//获取最大值
int Btree_max(BTnode* T) {
	BTnode* cur = T;
	while (cur->right) {
		cur = cur->right;
	}
	return cur->data;
}
//获取最小值
int Btree_min(BTnode* T) {
	BTnode* cur = T;
	while (cur->left) {
		cur = cur->left;
	}
	return cur->data;
}


//删除节点
void Btree_del(BTnode* T, DataType l) {
	if (!T) {
		printf("fuck no\n");
		return;
	}
	//找到这个要删除节点的父节点
	BTnode* p = T, * f = NULL;
	while (p) {
		if (p->data == l)
		{
			break;
		}
		f = p;
		p = l > p->data ? p->right : p->left;
	}
	if (!p)
	{
		printf("没有这个节点\n");
		return;
	}
	BTnode* target = p;//此时的要删除目标节点
	BTnode* par = f; //此时要删除节点的父节点

	//第一种情况 此节点只有一个子树的时候
	if (!target->left && target->right != NULL)
	{
		if (target->data > par->data) {
			par->right = target->right;
		}
		else {
			par->left = target->right;
		}
		free(target);//释放空间
		target = NULL;
	}
	else if (target->left != NULL && !target->right) {
		if (target->data > par->data) {
			par->right = target->left;
		}
		else {
			par->left = target->left;
		}
		free(target);
		target = NULL;
	}
	//第二种情况,如果删除的是叶节点,直接删除即可
	else if (!target->left && !target->right) {
		if (target->data > par->data) {
			par->right = NULL;
		}
		else {
			par->left = NULL;
		}
		free(target);
		target = NULL;
	}
	//第三种情况,如果左右子树都存在的话
	//可以用右子树的最小元素
	//或者左子树的最大元素来替代被删除的节点
	//我这里就直接去用左树的最大代替这个节点
	else
	{
		BTnode* Lchild = target->left;
		while (Lchild->right != NULL) {
			Lchild = Lchild->right;
		}
		if (target->data > par->data) {
			par->right = Lchild;
		}
		else {
			par->left = Lchild;
		}
		free(target);
		target = NULL;
	}
	printf("Deleting successfully\n");
}

//销毁
void Destory_btree(BTnode* T) {
	if (!T)
		return;
	BTnode* cur = T;
	if (cur->left)
		Destory_btree(cur->left);
	if (cur->right)
		Destory_btree(cur->right);
	free(T);
}

int main()
{
	int a[] = { 53,17,78,9,45,65,87,23 };
	//创建二叉排序树
	BTnode* T = Create_sortBtree(a, sizeof(a) / sizeof(int));
	mid_travel(T);//遍历输出
	puts("");
	//删除最大最小值
	printf("max:%d  min:%d\n", Btree_max(T), Btree_min(T));
	//查找
	BTnode* find = Btree_search(T, 23);
	printf("查找结果%d\n", find->data);

	//删除节点
	Btree_del(T, 45);
	mid_travel(T);
	puts("");
	//销毁操作
	Destory_btree(T);
}
//输出结果:
//9 17 23 45 53 65 78 87
//max:87  min : 9
//查找结果23
//Deleting successfully
//9 17 23 53 65 78 87


Lo anterior tiene que ver con el árbol de clasificación binaria. ¡Hasta la próxima! ¡Feliz Día Nacional a todos!

 Comparte un fondo de pantalla:

Supongo que te gusta

Origin blog.csdn.net/m0_73633088/article/details/133443742
Recomendado
Clasificación