[Estructura de datos] Implementación encadenada y recorrido de árboles binarios


Insertar descripción de la imagen aquí

1. recorrido del árbol binario

Los nodos del árbol binario en todos los códigos siguientes:

typedef char BTDataType;
//二叉树结点结构体
typedef struct BinaryTreeNode
{
    
    
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

1. Recorrido de reserva

Los recorridos de orden previo, medio y posterior se pueden resolver utilizando la idea de recursividad de divide y vencerás, y el nodo raíz y sus nodos secundarios se procesan por separado.

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        printf("NULL ");
        return;
    }

    printf("%c ", root->data);
    BinaryTreePrevOrder(root->left);
    BinaryTreePrevOrder(root->right);
}

Aquí solo utilizamos el gráfico de expansión recursiva para analizar el recorrido del pedido previo, y se utiliza la misma idea en orden y postorden:

Insertar descripción de la imagen aquí

Insertar descripción de la imagen aquí

2. Recorrido en orden

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        printf("NULL ");
        return;
    }

    BinaryTreeInOrder(root->left);
    printf("%c ", root->data);
    BinaryTreeInOrder(root->right);
}

3. Recorrido posterior al pedido

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        printf("NULL ");
        return;
    }

    BinaryTreePostOrder(root->left);
    BinaryTreePostOrder(root->right);
    printf("%c ", root->data);
}

4. Recorrido secuencial de capas

El recorrido del orden de nivel debe realizarse mediante una cola. Si el árbol binario y el nodo no están vacíos, dejemos queponer en cola un puntero a él, luego registre el nodo principal de la cola, imprima su valor primero, luego juzgue que sus hijos izquierdo y derecho no están vacíos y luego únase a la cola, luego elimine el encabezado de la cola y reemplácelo con el siguiente para continuar grabando e imprimiendo... hasta que la cola esté vacía y se complete el recorrido.

Por ejemplo, considere este árbol binario como se muestra:

El resultado del recorrido de la secuencia de capas es: 12345.
Insertar descripción de la imagen aquí
Primero, coloque el nodo raíz 1 en la cola e imprima 1

Insertar descripción de la imagen aquí

Luego agregue los niños izquierdo y derecho 2 y 3 de 1 al equipo.
Insertar descripción de la imagen aquí

Elimine el encabezado de la cola 1, reemplace el frente con 2 e imprima 2
Insertar descripción de la imagen aquí

Luego agregue el niño izquierdo 4 de 2 al equipo.
Insertar descripción de la imagen aquí

Elimine el encabezado 2, reemplace el frente con 3 e imprima 3
Insertar descripción de la imagen aquí

Luego agregue al niño correcto 5 de 3 al equipo.
Insertar descripción de la imagen aquí

……

Luego imprima 4 y 5 así para completar el recorrido de orden de nivel del árbol binario.

Insertar descripción de la imagen aquí

El código del programa utiliza la cola creada por él mismo, el código es el siguiente:

//层序遍历
void LevelOrder(BTNode* root)
{
    
    
    //创建队列
    Que q;
    QueueInit(&q);

    //如果根节点不为空,则放进队列
    if (root)
        QueuePush(&q, root);

    while (!QueueEmpty(&q))
    {
    
    
        //将队头打印
        BTNode* front = QueueFront(&q);
        printf("%c ", front->data);
        //判断front左右节点不为空则入队
        if (front->left)
            QueuePush(&q, front->left);

        if (front->right)
            QueuePush(&q, front->right);
        
        QueuePop(&q);
    }
    printf("\n");

    QueueDestroy(&q);
}

2. Número y altura de los nodos del árbol binario.

1. Número de nodos del árbol binario

Se implementa de forma recursiva utilizando el método divide y vencerás. Cuando el nodo raíz está vacío, el valor de retorno es 0. Si no está vacío, devuelve el número de nodos en los subárboles izquierdo y derecho más 1.

int BinaryTreeSize(BTNode* root)
{
    
    
    return root == NULL ? 0 : BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

2. Número de nodos hoja del árbol binario

Se implementa de forma recursiva utilizando el método divide y vencerás. Cuando el nodo raíz está vacío, se devuelve 0. Cuando el nodo raíz no tiene nodos secundarios, significa que es un nodo hoja y se devuelve 1. En otros casos, simplemente agregue los nodos hoja en los subárboles izquierdo y derecho.

int BinaryTreeLeafSize(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        return 0;
    }
    if (root->left == NULL && root->right == NULL)
    {
    
    
        return 1;
    }
    return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

3. Número de nodos en el k-ésimo nivel del árbol binario

Debe asegurarse de que k sea mayor que 0. Cuando el nodo raíz está vacío, se devuelve 0. Cuando k es igual a 1, solo hay un nodo en una capa y se devuelve 1. Cuando k>1, el número de nodos en la k-ésima capa es equivalente al k-ésimo hijo de sus hijos izquierdo y derecho. -Se suma el número de nodos en la capa 1.

int BinaryTreeLevelKSize(BTNode* root, int k)
{
    
    
    assert(k > 0);

    if (root == NULL)
    {
    
    
        return 0;
    }
    if (k == 1)
    {
    
    
        return 1;
    }
    return BinaryTreeLevelKSize(root->left, k - 1)
        + BinaryTreeLevelKSize(root->right, k - 1);
}

4. Encuentra el nodo con valor x en un árbol binario.

Si el siguiente nodo está vacío, se devuelve NULL si no se puede encontrar. Cuando el valor del nodo raíz es el valor que está buscando, se devuelve el nodo. Si no son iguales, se juzgan sus nodos secundarios izquierdo y derecho. respectivamente hasta que los encuentren.

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
    
    
    if (root == NULL)
    {
    
    
        return NULL;
    }
    if (root->data == x)
    {
    
    
        return root;
    }
    BTNode* ret = BinaryTreeFind(root->left,x);
    if (ret)
    {
    
    
        return ret;
    }
    return BinaryTreeFind(root->right, x);
}

3. Creación y destrucción de árboles binarios.

1. Cree un árbol binario atravesando la matriz en orden anticipado.

Lea una cadena transversal de pedido anticipado ingresada por el usuario y cree un árbol binario (almacenado como un puntero) basado en esta cadena. Por ejemplo, la siguiente cadena transversal de pedido anticipado: ABC##DE#G##F### donde "#" representa un espacio y el carácter de espacio representa un árbol vacío. Después de establecer el árbol binario, realice un recorrido en orden en el árbol binario y genere los resultados del recorrido.

#include <stdio.h>
#include<stdlib.h>
typedef char BTDataType;

typedef struct BinaryTreeNode {
    
    
    BTDataType data;
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
} BTNode;
BTNode* BinaryTreeCreate(BTDataType* a, int* pi) {
    
    
    if (a[*pi] == '#') {
    
    
        ++*pi;
        return NULL;
    }

    BTNode* root = (BTNode*)malloc(sizeof(BTDataType));
    root->data = a[*pi];
    ++*pi;

    root->left = BinaryTreeCreate(a, pi);
    root->right = BinaryTreeCreate(a, pi);

    return root;
}
//中序遍历
void InOrder(BTNode* root)
{
    
    
    if(root==NULL)
    {
    
    
        return;
    }
    InOrder(root->left);
    printf("%c ",root->data);
    InOrder(root->right);
}
int main() {
    
    
    char a[100];
    scanf("%s",a);
    int pi=0;
    BTNode* root=BinaryTreeCreate(a, &pi);
    InOrder(root);
    return 0;
}

2. Destrucción de árboles binarios

void BinaryTreeDestory(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        return;
    }

    BinaryTreeDestory(root->left);
    BinaryTreeDestory(root->right);
    free(root);
}

3. Determinar si es un árbol binario completo.

Modifique el recorrido de orden de nivel del árbol binario para que los nodos vacíos también ingresen a la cola. Al atravesar un nodo vacío, saldrá. Si hay nodos no vacíos antes del final del recorrido, no es un árbol binario completo.

int BinaryTreeComplete(BTNode* root)
{
    
    
    //创建队列
    Que q;
    QueueInit(&q);

    //如果根节点不为空,则放进队列
    if (root)
        QueuePush(&q, root);

    while (!QueueEmpty(&q))
    {
    
    
        BTNode* front = QueueFront(&q);
        if (front == NULL)
        {
    
    
            break;
        }
        QueuePush(&q, front->left);
        QueuePush(&q, front->right);
        QueuePop(&q);
    }
    //此时已经遇到空节点,如果再遇到非空节点则不是完全二叉树
    while (!QueueEmpty(&q))
    {
    
    
        BTNode* front = QueueFront(&q);
        if (front)
        {
    
    
            QueueDestroy(&q);
            return false;
        }
        QueuePop(&q);
    }

    QueueDestroy(&q);
    return true;
}

4. Código de prueba

Cree manualmente un árbol binario como se muestra a continuación y pruebe el código:
Insertar descripción de la imagen aquí
el resultado de la prueba debe ser:

Preorden: 123874569
Secuencia intermedia: 832715469
Postorden: 837259641

Si es un árbol binario completo: 0
Número de nodos: 9
Número de nodos hoja: 4

BTNode* BuyNode(BTDataType x)
{
    
    
    BTNode* node = (BTNode*)malloc(sizeof(BTNode));
    if (node == NULL)
    {
    
    
        perror("malloc fail");
        exit(-1);
    }

    node->data = x;
    node->left = NULL;
    node->right = NULL;

    return node;
}


int main()
{
    
    
    	// 手动构建
	BTNode* node1 = BuyNode('1');
	BTNode* node2 = BuyNode('2');
	BTNode* node3 = BuyNode('3');
	BTNode* node4 = BuyNode('4');
	BTNode* node5 = BuyNode('5');
	BTNode* node6 = BuyNode('6');
	BTNode* node7 = BuyNode('7');
	BTNode* node8 = BuyNode('8');
	BTNode* node9 = BuyNode('9');

	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;

	node2->right = node7;
	node3->left = node8;
	node6->right = node9;

    printf("前序遍历:");
    BinaryTreePrevOrder(node1);
	printf("\n");

    printf("中序遍历:");
    BinaryTreeInOrder(node1);
	printf("\n");

    printf("后序遍历:");
    BinaryTreePostOrder(node1);
	printf("\n");

    printf("层序遍历:");
    LevelOrder(node1);
    printf("\n");

    printf("BinaryTreeComplete:%d\n", BinaryTreeComplete(node1));
    printf("BinaryTreeSize:%d\n", BinaryTreeSize(node1));
    printf("BinaryTreeLeafSize:%d\n", BinaryTreeLeafSize(node1));

    BinaryTreeDestory(node1);
	node1 = NULL;

    return 0;
}

resultado de la operación:

Insertar descripción de la imagen aquí
Los resultados de ejecución son consistentes con los resultados previstos.

Supongo que te gusta

Origin blog.csdn.net/zcxyywd/article/details/133107365
Recomendado
Clasificación