Aprendizaje de la estructura de datos: Capítulo 4: Árboles y árboles binarios (árbol de ordenación binaria, árbol de equilibrio binario, árbol de Huffman)

Capítulo 4: Árboles y árboles binarios (Aplicaciones de árboles y árboles binarios: árbol de ordenación binaria, árbol equilibrado binario, árbol de Huffman)

1. Árbol de ordenación binaria

Árbol de ordenación binaria : BST, también conocido como árbol de búsqueda binaria

El árbol de clasificación binaria es un árbol vacío o un árbol no vacío. Cuando es un árbol no vacío, tiene las siguientes características:

  • Si el subárbol izquierdo no está vacío, entonces el valor clave de todos los nodos en el subárbol izquierdo es la clave del 均小于nodo raíz
  • Si el subárbol derecho no está vacío, el valor clave de todos los nodos del subárbol derecho es la clave del 均大于nodo raíz
  • Los propios subárboles izquierdo y derecho también son un árbol de clasificación binario.

Tenga en cuenta que aquí es menor que y mayor que pero no igual, lo que significa que no hay nodos con el mismo valor en el árbol de ordenación binaria.

Árbol de clasificación binaria

Recorrido en orden del árbol de ordenación binaria:1 2 3 4 5 6 8 10 16

Aquí se puede encontrar que el resultado del recorrido de orden medio del árbol de ordenación binaria aumenta con el tiempo, lo que es coherente con todos los árboles de ordenación binaria.

Una secuencia ordenada creciente cuando el orden medio de un árbol de ordenamiento binario atraviesa la secuencia

1.1 Encontrar un árbol de ordenación binaria

  • Cuando el árbol binario no está vacío, busque el nodo raíz, y si es igual, la búsqueda es exitosa;
  • Si no es igual, cuando es menor que el valor del nodo raíz, busque el subárbol izquierdo; cuando sea mayor que el valor del nodo raíz, busque el subárbol derecho.
  • Cuando se encuentra el nodo hoja pero no se encuentra el valor correspondiente, la búsqueda falla.

Árbol de clasificación binaria

Ejercicio:

Encuentre 5: el primer 8> 5 encuentra el subárbol izquierdo, 5> 4 encuentra el subárbol derecho, 5 = 5 encuentra una
búsqueda exitosa 6: el primer 8> 6 encuentra el subárbol izquierdo, 6> 4 encuentra el subárbol derecho, 6> 5 encuentra el subárbol derecho, 6 <7 La búsqueda del subárbol izquierdo está vacía y falla.

De acuerdo con este proceso, es realmente fácil encontrar que todo el proceso de búsqueda se puede completar usando la recursividad, y puede probarlo usted mismo. Aquí usamos consultas no recursivas. Escritura de código:

Ref. 1 Árbol Binario, Ref. 2 Palabra Clave Parámetro 3, guarda el nodo padre del nodo encontrado. Es una variable de referencia de puntero. Cuando se modifica el puntero en el cuerpo de la función, no solo se modificarán los parámetros formales, sino también Modifica el puntero de variable que pasamos.

BSTNode *BST_Search(BiTree T,ElemType key,BSTNode *&p){
    
    
    p = NULL; //双亲结点置为空(根结点没有双亲结点)
    while(T != NULL && key != T->data){
    
    //树非空且关键字不匹配
       p = T; //p指向改结点
       if(key < T->data){
    
    
           T = T->lchild; //循环查找左子树
       }else{
    
    
           T = T->rchild; //循环查找右子树
       }
    }
    return T;
}

Complejidad de tiempo : O (h) (h es la altura del árbol de ordenación binaria)

1.2 Inserción del árbol de ordenación binaria

  • Si el árbol de clasificación binario está vacío, inserte el nodo directamente;
  • Si el árbol de ordenamiento binario no está vacío, cuando el valor es menor que el nodo raíz, inserte el subárbol izquierdo; cuando el valor sea mayor que el nodo raíz, inserte el subárbol derecho; cuando el valor sea igual al nodo raíz, haga no insertar

Árbol de clasificación binaria

Ejercicio:

Inserte 6: 6 <8 en el subárbol izquierdo, 6> 4 en el subárbol derecho y 6> 5 en el subárbol izquierdo.

Árbol de clasificación binaria

Escritura de código:

//参1 二叉树(注意是引用),参2 插入值
int BST_Insert(BiTree &T,KeyType k){
    
    
	if(T==NULL){
    
     //树为空
		T = (BiTree)malloc(sizeof(BSTNode));
		T->key = k;
		T->lchild = T->rchild = NULL;
		return 1;
	}else if(k == T->key){
    
     //相同不插入
		return 0;
	}else if(k < T->key){
    
    //小于插入左子树中,递归调用
		return BST_Insert(T->lchild,k);
	}else{
    
    //大于插入右子树中,递归调用
		return BST_Insert(T->rchild,k);
	}
}

1.3 Construyendo un árbol de ordenamiento binario

Leer un elemento y crear un nodo. Si el árbol binario está vacío, utilícelo como nodo raíz; si el árbol de ordenación binario no está vacío, cuando el valor sea menor que el nodo raíz, inserte el subárbol izquierdo; cuando el valor es mayor que el nodo raíz, inserte el subárbol derecho; cuando el valor es igual al nodo raíz, no se realiza ninguna inserción.

//参3 插入结点的数量
void Create_BST(BiTree &T,KeyType str[],int n){
    
    
	T = NULL;
	int i=0;
	while(i<n){
    
    
		BST_Insert(T,str[i]);
		i++;
	}
}

El proceso de construcción del árbol de clasificación binaria incluso si los valores de las dos matrices son exactamente iguales, pero el orden de construcción es diferente, el árbol de clasificación binario resultante es diferente.

1.4 Eliminación del árbol de ordenación binaria

Supongamos que eliminamos 4 nodos, ¿cómo deberían los subárboles izquierdo y derecho de los 4 nodos restantes formar el subárbol izquierdo del nodo 8?

Para mantener la naturaleza básica del árbol binario, la operación de eliminación es en realidad más complicada. Necesitamos dividirlo en tres situaciones:

  • 1. Si el nodo z eliminado es un nodo hoja, se puede eliminar directamente sin afectar
  • 2. Si el nodo z eliminado tiene sólo un subárbol, deje que el subárbol de z se convierta en el subárbol del nodo padre de z, con el título del nodo z.

Por ejemplo, eliminamos el nodo 5


  • 3. Si el nodo z eliminado tiene dos subárboles, deje que la secuencia en orden de z reemplace directamente z, y elimine el nodo sucesor directo.

Por ejemplo, si eliminamos el nodo 4, sabemos que el sucesor inmediato del nodo 4 es el nodo más a la izquierda del subárbol derecho de 4, aquí hay 5, reemplazamos directamente el nodo 4 con el nodo 5, y luego directamente Simplemente eliminamos el nodo 5. ¿Por qué se puede eliminar directamente aquí? Debido a que este nodo debe ser el nodo más a la izquierda, no hay un subárbol (nodo hoja), o solo el subárbol derecho (si hay un subárbol a la izquierda, no es el nodo más a la izquierda), así que elimínelo Simplemente consulte las dos situaciones anteriores directamente .


Pensamiento:
elimine e inserte un nodo en el árbol de ordenación binaria. ¿Es el árbol de ordenación binario el mismo que el original?

Primero borramos un nodo 7:

Luego inserte el nodo 7

En este momento, se encuentra que el árbol de clasificación binaria es el mismo después de la eliminación y la inserción. Este es el caso de eliminar los nodos hoja. Después de la eliminación y la inserción, el árbol de clasificación binaria es el mismo. ¿Hay alguna diferencia?

Si borramos el 5 de un nodo padre

Luego inserte el nodo 5

En este punto, encontramos que el árbol de ordenamiento binario es diferente después de la eliminación y la inserción.

Por lo tanto: al eliminar e insertar un nodo en el árbol de clasificación binaria, dependiendo del tipo de nodo eliminado e insertado, el árbol de clasificación binario resultante puede ser el mismo o diferente.

1.5 eficiencia de búsqueda

Duración de la búsqueda : la cantidad de nodos experimentados al buscar este nodo.

Longitud de búsqueda promedio (ASL) : la suma de las longitudes de búsqueda de todos los nodos toma el valor promedio, que depende de la altura del árbol.

P.ej:

Eficiencia de búsqueda : O (log2n)

Eficiencia de búsqueda : O (n)

2. Árbol binario equilibrado

Árbol binario equilibrado : AVL, cualquier nodo 平衡因子es 绝对值menor que uno.

Factor de equilibrio: la altura del subárbol izquierdo altura del subárbol -derecho

El árbol binario que se muestra en la figura anterior, ¿es un árbol binario equilibrado?

El factor de equilibrio de todos los nodos se puede calcular y juzgar, y se puede ver que el árbol binario es un árbol binario equilibrado.

¿El 最小(结点数最少)平衡二叉树número de nodos con altura h, Nh?

De acuerdo con el valor del nodo en el lado derecho del árbol binario balanceado, puede elegir: h, h-1 y h-2. Si elige h, más 1 nivel del nodo raíz, el número total de niveles es h + 1, que no cumple con el significado de la pregunta. Entre ellos, se pueden seleccionar h-1 y h-2, pero ¿por qué elegir h-2? Esto se debe a que estamos hablando de un árbol binario balanceado mínimo, y el número de nodos en el nivel h-1 es definitivamente mayor que el número de nodos en el nivel h-2. N0 = 0 (el número de nodos en el nivel 0 es 0) N1 = 1 (el número de nodos es 1)

Por ejemplo, ahora queremos calcular el número de nodos del árbol binario balanceado mínimo con una altura de 3. luego:

N3 = N2 + N1 + 1; =》 N2 = N1 + N0 + 1 = 2; =》 N3 = 2 + 1 + 1 = 4;

2.1 Juicio del árbol binario equilibrado

Utilice el proceso transversal recursivo posterior al pedido:

  • Determine que el subárbol izquierdo es un árbol binario equilibrado
  • Determine que el subárbol correcto es un árbol binario equilibrado
  • Juzgue el árbol binario enraizado en este nodo como un árbol binario balanceado.
    Condiciones de juicio
    Si el subárbol izquierdo y el subárbol derecho son árboles binarios balanceados y el valor absoluto de la diferencia de altura entre el subárbol izquierdo y el subárbol derecho es menor o igual que a 1, está equilibrado.

De acuerdo con la condición de juicio, sabemos que cada nodo necesita guardar dos variables: una es el balance del nodo (b: 1 balance 0 desbalance) y la otra es la altura del nodo (h).

//参1 该棵树的根节点
void Judge_AVL(BiTree bt,int &balance,int &h){
    
    
    //左子树平衡性左子树高度 右子树平衡性右子树高度
	int bl=0,br=0,hl=0,hr=0;
	if(bt==NULL){
    
    //如果根节点为空
		h=0; //高度设为0
		balance=1; //并且是平衡的
	}else if(bt->lchild==NULL&&bt->rchild==NULL){
    
    
	    //左子树和右子树都为空
		h=1; //高度为1
		balance=1; //平衡的
	}else{
    
    
		Judge_AVL(bt->lchild,bl,hl); //判断左子树
		Judge_AVL(bt->rchild,br,hr); //判断右子树
		//下面计算该节点为根二叉树的高度
		//首先判断哪个子树的高度高,然后加1即可
		if(hl>hr){
    
    
			h=hl+1;
		}else{
    
    
			h=hr+1;
		}
		//判断平衡性
		// abs 是取绝对值
		if(abs(hl-hr)<2&&bl==1&&br==1){
    
    
			balance=1;
		}else{
    
    
			balance=0;
		}
	}
} 

3. Inserción equilibrada de árbol binario

El proceso de inserción del árbol binario equilibrado es en realidad un paso más que el proceso de inserción del árbol de ordenación binaria. Si se sigue el proceso de inserción del árbol de ordenación binaria, el árbol binario formado no es necesariamente un árbol binario equilibrado, por lo que necesitamos para insertarlo primero y luego ajustarlo. A saber:先插入后调整 .

Principio de ajuste : ajuste el subárbol desequilibrado mínimo cada vez

Por ejemplo, como se muestra en la figura anterior, necesitamos ajustar después de que se completa la inserción Nuestro ajuste comienza desde el nodo de inserción y se mueve hacia arriba. Primero, el factor de equilibrio de 4 nodos es -1, que se ajusta al árbol binario equilibrado, y luego el factor de equilibrio de 6 nodos ascendente es 2, que no se ajusta al árbol binario equilibrado y debe ajustarse.

Rotación de equilibrio 3.1LL (rotación simple derecha)

La razón del desequilibrio : se inserta un nuevo nodo en el subárbol izquierdo del hijo izquierdo del nodo A.

Método de ajuste : Operación para diestros: Reemplace A con el hijo izquierdo B de A, llame al nodo A como el nodo raíz del subárbol derecho de B y el subárbol derecho original de B como el subárbol izquierdo de A.

Cuando haya un desequilibrio, ajuste lo siguiente a un árbol binario equilibrado:

Rotación de equilibrio 3.2RR (rotación simple izquierda)

La razón del desequilibrio : se inserta un nuevo nodo en el subárbol izquierdo del hijo derecho del nodo A.

Método de ajuste : Operación para zurdos: reemplace A con el hijo derecho B de A, llame al nodo A el nodo raíz del subárbol izquierdo de B y al subárbol izquierdo original de B como el subárbol derecho de A.

Rotación de equilibrio 3.3LR (primera rotación doble a la izquierda y luego a la derecha)

La razón del desequilibrio : se inserta un nuevo nodo en el subárbol derecho del hijo izquierdo del nodo A.

Método de ajuste : primero operación para zurdos y luego para diestros: reemplace el nodo C del hijo derecho del hijo izquierdo de A B, y luego reemplace la posición de A con el nodo C hacia arriba.

Nota: Cl y Cr también pueden estar vacíos, porque el subárbol derecho Br de B puede estar vacío.

Rotación de equilibrio 3.4RL (doble rotación de derecha e izquierda)

La razón del desequilibrio : se inserta un nuevo nodo en el subárbol izquierdo del hijo izquierdo del nodo A.

Método de ajuste : Gire a la derecha y luego gire a la izquierda Operación: Reemplace el nodo C del hijo izquierdo del hijo derecho B de A, y luego reemplace la posición de A con el nodo C hacia arriba.

4. Longitud del camino ponderado

Antes de aprender Huffman, primero debe comprender la longitud de la ruta ponderada

Ruta de longitud de ruta experimentada: número

El peso del nodo: el valor asignado al nodo

Árbol de ruta de longitud ponderada : WPL, todos los árboles en 叶结点la suma ponderada de las longitudes de ruta

La longitud de la ruta ponderada del árbol binario anterior es :WPL=7*2+2*2+3*2=24

La longitud de la ruta ponderada del árbol binario anterior es :WPL=7*1+2*2+3*2=17

Podemos ver que aunque los pesos de los nodos de los dos árboles binarios son los mismos, sus longitudes de camino ponderadas no son las mismas, lo que nos lleva a哈夫曼树的定义

5. Árbol de Huffman

Árbol de Huffman : también llamado árbol binario óptimo, un árbol binario con n nodos de hojas ponderados con la longitud de ruta ponderada más pequeña.

5.1 La estructura del árbol de Huffman

Algoritmo de construcción del árbol de Huffman

  • Tome n nodos como n árboles binarios con un solo nodo raíz para formar un bosque F
  • Genere un nuevo nodo y encuentre los dos árboles con el menor peso del nodo raíz de F como sus subárboles izquierdo y derecho, y el peso del nuevo nodo es la suma de los pesos de los nodos raíz de los dos subárboles.
  • Elimine estos dos árboles de F y agregue el árbol recién generado a F
  • Repita los pasos 2 y 3 hasta que solo haya un árbol en F

Cabe señalar aquí que el proceso de construcción del árbol de Huffman no requiere ese árbol como subárbol izquierdo y el árbol como subárbol derecho, por lo que el árbol de Huffman no es único.

Por ejemplo, el ejemplo anterior:

El primero son tres nodos ponderados ABC

Luego seleccione los dos árboles B y C con el menor peso del nodo raíz para formar un árbol binario, el peso del nodo raíz del árbol binario es la suma de los pesos de los dos nodos, y luego vuelva a colocarlo en el bosque.

Entonces aún elija los dos árboles con el menor peso del nodo raíz ...

5.2 La naturaleza del árbol de Huffman

  • Cada nodo inicial se convierte en un nodo hoja y los nodos de doble rama son nodos recién generados
  • Cuanto mayor sea el peso, más cerca del nodo raíz, y cuanto menor sea el peso, más lejos del nodo raíz.
  • El grado sin nodo en el árbol de Huffman es 1
  • El número total de nodos en un árbol de Huffman con n nodos hoja es 2n-1, y el número de nodos con grado 2 es n-1

5.3 codificación Huffman

Codificación : para una secuencia de cadenas, use binario para representar caracteres

Codificación de longitud fija :

Por ejemplo: HelloWorld, donde cada carácter usa una representación binaria de tres dígitos, de la cual podemos obtener la secuencia binaria correspondiente a la cadena: 000001010010011100011101010110.

A partir del código anterior, podemos tener dos dudas: 1. ¿Por qué usar un código de tres dígitos? Representación binaria, en lugar de una representación binaria más corta, como de dos dígitos? 2. Los lcaracteres aparecen con más frecuencia, ¿pueden estos caracteres con más ocurrencias utilizar códigos más cortos para obtener secuencias binarias más cortas? Esto conduce al segundo método de codificación:可变长度编码

Codificación de longitud variable :

Por ejemplo: HelloWorld, usamos una representación binaria relativamente corta, de la cual podemos obtener la secuencia binaria correspondiente a la cadena: 0001001101110000

Se puede ver que dicha secuencia es mucho más corta que la secuencia anterior, pero dicha secuencia no es aplicable porque usamos una codificación de longitud fija para representar un carácter cada tres dígitos, y la cadena correspondiente se puede obtener atravesando a su vez Pero ahora los códigos de longitud variable como 00 pueden representar el carácter H o ​​dos caracteres l, lo que crea ambigüedad. De hecho, la codificación de prefijo está disponible.

Codificación de prefijo : ninguna de las codificaciones es el prefijo de otra

Modificamos la tabla correspondiente de arriba para:

Nosotros modificamos l a 11, que no es un prefijo de cualquier código, de modo que la secuencia binaria formada puede invertirse en una cadena.

Entonces, ¿cómo se obtiene tal codificación de prefijo? De hecho, aprovecha las características del árbol de Huffman. Da una castaña: cinco letras y el número de ocurrencias: A: 5 B: 3 C: 6 D: 9 E: 13, usamos el algoritmo de construcción del árbol de Huffman para construir un árbol de Huffman, en primer lugar, cada letra se usa como Un nodo, y su peso es su número de ocurrencias.

Luego construye el árbol de Huffman

Entonces solo necesitamos asignar todos los bordes izquierdos en el árbol a 0 y los bordes derechos a 1

Luego usamos el borde experimentado desde el nodo raíz hasta cierto nodo, podemos obtener el código de prefijo correspondiente al nodo: D 00-E 01-C 10-A 110-B 111, y podemos ver que el número de ocurrencias Cuanto más nodos, más corto es el código de prefijo y más largo el código del nodo con menos ocurrencias, lo que también logra el propósito de acortar la secuencia binaria.

Finalmente, debemos prestar atención a:

El árbol de Huffman no es único, por lo que el código de Huffman correspondiente a cada carácter tampoco es único, pero la longitud de la ruta ponderada es la misma y óptima

Sin conocimiento de la estructura de datos públicos que procesa la madera de la actualización sincrónica, la próxima vez lo explicará: diagramas de estructura de datos , bienvenida a la atención de todos

Supongo que te gusta

Origin blog.csdn.net/qq_41941875/article/details/106522994
Recomendado
Clasificación