[Likou] Restaure el árbol binario de acuerdo con los resultados transversales del árbol binario en orden previo y en orden (y la restauración en orden posterior y en orden)

Un árbol binario restaurado en orden y pre-pedido

Conexión: restaure el árbol binario de acuerdo con los resultados del recorrido en orden previo y en orden del árbol binario
inserte la descripción de la imagen aquí

La idea es esta:

  • El propósito de este algoritmo es reconstruir un árbol binario basado en los resultados del recorrido en orden previo y el recorrido en orden.
  • La característica del recorrido previo al pedido es que el primer elemento debe ser el nodo raíz, y los siguientes elementos son el recorrido previo al pedido del subárbol izquierdo y el subárbol derecho.
  • La característica del recorrido en orden es que el nodo raíz está en el medio del subárbol izquierdo y el subárbol derecho, el elemento de la izquierda es el recorrido en orden del subárbol izquierdo y el elemento de la derecha es el recorrido en orden de el subárbol derecho.
  • Por lo tanto, podemos usar el recorrido en orden previo para determinar el nodo raíz y luego encontrar la ubicación del nodo raíz en el recorrido en orden, dividiendo así el intervalo entre el subárbol izquierdo y el subárbol derecho.
  • Luego hacemos lo mismo recursivamente para los subárboles izquierdo y derecho hasta que el intervalo esté vacío o tenga solo un elemento.
  • Finalmente, devolvemos el nodo raíz del árbol binario reconstruido.

Código con comentarios:

class Solution {
    
     
public: 
  //后序确定根 
  //中序分割左右区间 
  TreeNode* _buildTree(vector<int>& inorder, vector<int>& postorder, int& posti, int ibegin, int iend) {
    
     
    if (ibegin > iend) return nullptr; //如果中序区间为空,返回空指针
    TreeNode* root = new TreeNode(postorder[posti]); //创建根节点,值为后序遍历的最后一个元素
    //分割左右子区间 
    int rooti = ibegin; //找到根节点在中序遍历中的位置
    while (rooti <= iend) {
    
     
      if (inorder[rooti] == postorder[posti]) break; //找到了,跳出循环
      else rooti++; //没找到,继续向右移动
    } 
    --posti; //后序遍历的索引向前移动一位
    root->right = _buildTree(inorder, postorder, posti, rooti+1, iend); //递归构建右子树,中序区间为[rooti+1, iend]
    root->left = _buildTree(inorder, postorder, posti, ibegin, rooti-1); //递归构建左子树,中序区间为[ibegin, rooti-1]
    return root; //返回根节点
  } 
  TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
    
     
    int i = postorder.size()-1; //初始化后序遍历的索引为最后一位
    return _buildTree(inorder, postorder, i, 0, inorder.size()-1); //调用辅助函数,中序区间为[0, inorder.size()-1]
  } 
};

Postorder binario y reducción inorder de árboles binarios

¿Qué sucede si el pedido posterior y el pedido en orden le permiten restaurar el árbol binario?
Enlace: post-orden y restauración en orden de un árbol binario

Sigue siendo la misma idea que la anterior, pero esta vez el subárbol derecho debe construirse recursivamente primero, porque la característica del recorrido posterior al pedido es que el último elemento es el nodo raíz y los elementos anteriores son el posterior al pedido. recorrido del subárbol izquierdo y el subárbol derecho, y el subárbol derecho está detrás del subárbol izquierdo. Por lo tanto, primero debemos construir recursivamente el subárbol derecho y luego construir el subárbol izquierdo, para asegurarnos de que el índice de recorrido posterior al pedido sea correcto.

inserte la descripción de la imagen aquí

  • El último elemento del recorrido posterior al pedido es el nodo raíz del árbol binario.
  • Encuentre la posición del nodo raíz en el recorrido en orden. La secuencia a la izquierda del nodo raíz es el recorrido en orden del subárbol izquierdo, y la secuencia a la derecha es el recorrido en orden del subárbol derecho. .
  • En el recorrido posterior al orden, encuentre la secuencia correspondiente del subárbol izquierdo y el subárbol derecho. La longitud del subárbol izquierdo es la misma que la longitud del subárbol izquierdo en el recorrido en orden, y lo mismo es cierto para el subárbol derecho.
  • Repita los pasos anteriores de forma recursiva para los subárboles izquierdo y derecho hasta que el recorrido posterior al orden o el recorrido en orden esté vacío.

Por ejemplo, dado el recorrido en orden posterior [9, 15, 7, 20, 3] y el recorrido en orden [9, 3, 15, 20, 7], el proceso de restauración de un árbol binario es el siguiente:

  • El último elemento del recorrido posterior al orden es 3, que es el nodo raíz del árbol binario.
  • Encuentre la posición de 3 en el recorrido en orden, la secuencia [9] a la izquierda es el recorrido en orden del subárbol izquierdo, y la secuencia [15, 20, 7] a la derecha es el recorrido en orden del subárbol derecho .
  • Encuentre la secuencia del subárbol izquierdo y el subárbol derecho correspondientes en el recorrido posterior al orden. El subárbol izquierdo tiene solo un elemento [9], y el subárbol derecho tiene tres elementos [15, 7, 20].
  • Restaure recursivamente el árbol binario al subárbol izquierdo. Dado que el recorrido posterior al orden y el recorrido en orden tienen solo un elemento, el nodo secundario izquierdo es 9.
  • Restaure recursivamente el árbol binario al subárbol derecho. Dado que el recorrido posterior al pedido y el recorrido en orden están vacíos, repita los pasos anteriores.

código:

class Solution {
    
     
public: 
  //后序确定根 
  //中序分割左右区间 
  TreeNode* _buildTree(vector<int>& inorder, vector<int>& postorder, int& posti, int ibegin, int iend) {
    
     
    if (ibegin > iend) return nullptr; //如果中序区间为空,返回空指针
    TreeNode* root = new TreeNode(postorder[posti]); //创建根节点,值为后序遍历的最后一个元素
    //分割左右子区间 
    int rooti = ibegin; //找到根节点在中序遍历中的位置
    while (rooti <= iend) {
    
     
      if (inorder[rooti] == postorder[posti]) break; //找到了,跳出循环
      else rooti++; //没找到,继续向右移动
    } 
    --posti; //后序遍历的索引向前移动一位
    root->right = _buildTree(inorder, postorder, posti, rooti+1, iend); //递归构建右子树,中序区间为[rooti+1, iend]
    root->left = _buildTree(inorder, postorder, posti, ibegin, rooti-1); //递归构建左子树,中序区间为[ibegin, rooti-1]
    return root; //返回根节点
  } 
  TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
    
     
    int i = postorder.size()-1; //初始化后序遍历的索引为最后一位
    return _buildTree(inorder, postorder, i, 0, inorder.size()-1); //调用辅助函数,中序区间为[0, inorder.size()-1]
  } 
};

final de esta sección

Supongo que te gusta

Origin blog.csdn.net/weixin_62676865/article/details/130466686
Recomendado
Clasificación