Solución de problema de árbol binario general "Estructura de datos elemental" - Escritura recursiva

prefacio

En cuanto al método de escritura recursiva de árboles binarios ordinarios, es simple de escribir, pero un poco difícil de entender.Requiere la base de recorrido previo, en orden y posterior al pedido. La resolución de problemas en este capítulo no dibuja un diagrama de expansión recursivo, sino que solo proporciona pensamiento y código.

1. El enfoque de este capítulo

  1. .árbol binario de un solo valor
  2. Comprobar si dos árboles son iguales
  3. árbol binario simétrico
  4. subárbol de otro árbol
  5. Construcción y recorrido del árbol binario.

2. Árbol binario de valor único

bool isUnivalTree(struct TreeNode* root)

 Idea recursiva: cuando la raíz es NULL, devuelve verdadero.

Cuando existe el hijo izquierdo, devuelve falso si el valor del hijo izquierdo no es igual al valor del nodo raíz.

De manera similar, cuando existe el hijo derecho, si el valor del hijo derecho no es igual al valor del nodo raíz, devuelve falso.

A continuación, conozca:

return isUnivalTree(root->left) && isUnivalTree(root->right);

Código de referencia:

bool isUnivalTree(struct TreeNode* root)
{
    if(root==NULL)
    {
        return true;
    }
    if(root->right && root->val!=root->right->val)
    {
        return false;
    }
    if(root->left && root->val!=root->left->val)
    {
        return false;
    }
    //以上三个if为递归的出口
    return isUnivalTree(root->left) && isUnivalTree(root->right);//分治,安排任务下去
}

Si te sientes un poco increíble después de escribir, necesitas dibujar un diagrama de expansión recursivo y realizar pasos recursivos en tu mente.

Escribir recursividad por primera vez es mejor entenderlo dibujando.

3. Comprueba si los dos árboles son iguales .

bool isSameTree(struct TreeNode* p, struct TreeNode* q)

Idea recursiva:

Devuelve verdadero cuando p está vacío y q está vacío

Cuando uno de p y q está vacío y el otro no lo está, devuelve falso.

Cuando p->val! =q->val, devuelve verdadero.

Al final:

 return isSameTree(p->left,q->left)
    &&isSameTree(p->right,q->right);

Código de referencia:

bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
    if(p==NULL && q==NULL)
    {
        return true;
    }
    if(p==NULL||q==NULL)
    {
        return false;
    }
    if(p->val!=q->val)
    {
        return false;
    }
    return isSameTree(p->left,q->left)
    &&isSameTree(p->right,q->right);
}

4. Árbol binario simétrico

bool isSymmetric(struct TreeNode* root)

Idea recursiva: si la raíz es NULL, devuelve verdadero.

Al juzgar que los dos árboles, el subárbol izquierdo y el subárbol derecho, son simétricos, el prototipo de función aquí solo contiene una raíz, lo que obviamente no funciona. Aquí reescribimos una subfunción:

bool _isSymmetric(struct TreeNode* left,struct TreeNode* right)

Si tanto la izquierda como la derecha son iguales a NULL, los dos árboles son simétricos.

Si uno está vacío y el otro no, es asimétrico.

Si ninguno está vacío: si izquierda->val!=derecha->val, devuelve falso.

Al final:

   return  _isSymmetric(left->left,right->right)
            &&_isSymmetric(left->right,right->left);

Código de referencia:

bool _isSymmetric(struct TreeNode* left,struct TreeNode* right)
{
    if(left==NULL && right==NULL)
    {
        return true;
    }
    if(left==NULL||right==NULL)
    {
        return false;
    }
    if(left->val!=right->val)
    {
        return false;
    }
   return  _isSymmetric(left->left,right->right)
            &&_isSymmetric(left->right,right->left);
}

bool isSymmetric(struct TreeNode* root)
{
    if(root==NULL)
    {
        return true;
    }
    return _isSymmetric(root->left,root->right);
}

 5. Subárboles de otro árbol

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)

Descripción del tema: puede considerarse como su propio subárbol 

Escritura recursiva:

Para juzgar si es un subárbol, comience desde sí mismo y use la pregunta 3 anterior para juzgar si los dos árboles tienen el mismo código.

Si:

 if(isSameTree(root,subRoot))
 {
    return true;
 }

Juzga de nuevo:

return isSubtree(root->right,subRoot)
           ||isSubtree(root->left,subRoot);

Pero no olvide escribir root==NULL, de lo contrario, root->right saldrá mal y no habrá una salida recursiva.

Código de referencia:


bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
    if(p==NULL && q==NULL)
    {
        return true;
    }
    if(p==NULL||q==NULL)
    {
        return false;
    }
    if(p->val!=q->val)
    {
        return false;
    }
    return isSameTree(p->left,q->left)
    &&isSameTree(p->right,q->right);
}

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
    if(isSameTree(root,subRoot))
    {
        return true;
    }
    if(root==NULL)
    {
        return false;
    }
    return isSubtree(root->right,subRoot)
           ||isSubtree(root->left,subRoot);
}

6. Recorrido de árbol binario

 Esta es una pregunta de Niu Ke, una pregunta tipo io.

ingresar:

char string[100];
scanf("%s",string);

Lo primero: construye un árbol binario encadenado de cadenas, ya que es una cadena de preorden, se puede recibir mediante un recorrido de preorden.

Código de referencia:

TreeNode* CreatBinaryTree(char* s,int* i)
{
    if(s[*i]=='#')
    {
        (*i)++;
        return NULL;
    }
    TreeNode* root=(TreeNode*)malloc(sizeof(TreeNode));
    root->val=s[*i];
    (*i)++;
    root->left=CreatBinaryTree(s,i);
    root->right=CreatBinaryTree(s,i);
    return root;
}

Después de construir el árbol binario, use el recorrido en orden.

Código de referencia:

void PrevOrder(TreeNode* root)
{
    if(root==NULL)
    {
        return;
    }
    PrevOrder(root->left);
    printf("%c ",root->val);
    PrevOrder(root->right);
}

Supongo que te gusta

Origin blog.csdn.net/m0_62171658/article/details/124066705
Recomendado
Clasificación