Utilizar cualquier reconstrucción recorrido de dos árboles binarios

prefacio

Aprender a utilizar la pre-orden de recorrido y recorrido de secuencia para reconstruir el árbol binario, estaba pensando acerca de si o no saber dos cualquiera de recorrido, árbol binario puede ser reconstruido fuera de él? Un estudio cuidadoso de una noche, es realmente el caso.

Encuentra la ley

Mira las tres clases de recorrido

struct Tree{
    int val;
    Tree *left;
    Tree *right;
};

void printTree(Tree *node,int mode){
    if(node!=nullptr){
        switch(mode){
            case 1:
                cout<<node->val<<",";
                printTree(node->left, mode);
                printTree(node->right, mode);
                break;
            case 2:
                printTree(node->left, mode);
                cout<<node->val<<",";
                printTree(node->right, mode);
                break;
            case 3:
                printTree(node->left, mode);
                printTree(node->right, mode);
                cout<<node->val<<",";
                break;
            default:
                break;
        }
    }
}

Código no dice, comprender, antes de la correspondiente 1,2,3 respectivamente, en el recorrido de orden posterior.

La primera y más importante regla es, eliminar los datos del nodo raíz, cada llamada a la función es la primera salida de todos los datos subárbol izquierdo, y luego la salida los datos subárbol derecho. Esta ley no tiene nada que ver con la recursividad, yo creo que debe ser fácil de encontrar.

//cout<<node->val<<",";
printTree(node->left, mode);
//cout<<node->val<<",";
printTree(node->right, mode);
//cout<<node->val<<",";

Además de la segunda regla, la salida de cada uno de los pre-pedido de recorrido de un nodo raíz debe ser los datos, en el orden posterior recorrido contrario, el último es los datos de salida de cada nodo raíz.

Preorden recorrido y preorden

Preorden recorrido: 3,0,1,2,6,5,4,8,7,9
preorden: 0,1,2,3,4,5,6,7,8,9

De acuerdo con la ley de recorrido en preorden, podemos saber el nodo raíz 3. Vamos a arrancar de raíz a través preorden dividido en sub-árbol izquierdo y subárbol derecho.

Preorden: [0, 1] [3] [4,5,6,7,8,9]
root: 3
subárbol izquierdo: 0,1,2
subárbol derecho: 4,5,6 , 7,8,9

En este momento, sabiendo el número de sub-árbol izquierdo y derecho, preorden recorrido también se puede dividir en sub-árbol subárbol izquierdo y derecho

Preorden recorrido: [3] [0,1,2] [6,5,4,8,7,9]
root: 3
subárbol izquierdo: 0,1,2
subárbol derecho: 6,5,4 , 8,7,9

Generación de nuevos subárbol izquierdo y el subárbol derecho de la operación anterior se repite hasta que cada nodo como el nodo raíz a través.

Mira el código de implementación:

//pre:前序遍历
//mid:中序遍历
//length:数组长度
Tree* Fun1(const int *pre, const int *mid,const int length) {
	//当空指针或者数组长度为0时返回
	if (pre == NULL || mid == NULL || length <= 0) 
	    return NULL;

	//建立根节点
	Tree *head = new Tree();
	head->value=pre[0];
	head->left=head->right=NULL;

	//找到中序遍历中根节点所在位置
	int index = 0;
	while (index<length) {
		if (head->value == mid[index])
			break;
		++index;
	}

	//划分左子树
	head->left = Fun1(pre + 1, mid, index);
	//划分右子树
	head->right = Fun1(pre + index +1, mid + index + 1, length - index - 1);

	return head;
}

Preorden y postorden

Principio es básicamente el mismo que el anterior, excepto que el nodo raíz en una matriz Finalmente, aquí no es explicar, espero que pueda por sí misma.

//mid:中序遍历
//back:后序遍历
//length:数组长度
Tree* Fun2(const int *mid,const int *back,const int length){
    //当空指针或者数组长度为0时返回
    if(back==NULL||mid==NULL||length<=0)
        return NULL;
    
    //建立根节点
    Tree *head=new Tree();
    head->val=back[length-1];
    head->left=head->right=NULL;
    
    //找到中序遍历中根节点所在位置
    int index=0;
    while(index<length){
        if(head->val==mid[index]){
            break;
        }
        ++index;
    }
    
    //划分左子树
    head->left=Fun2(mid,back,index);
    //划分右子树
    head->right=Fun2(mid+index+1, back+index, length-index-1);
    
    return head;
}

Preorden de recorrido y de orden posterior

Preorden recorrido: 3,0,1,2,6,5,4,8,7,9
recorrido posterior a la orden: 2,1,0,4,5,7,9,8,6,3

Leer la derivación anterior, creo que para encontrar la raíz de datos 3 para todo el mundo un poco difícil en absoluto. La dificultad es cómo separar el subárbol izquierdo y subárbol derecho.
Una mirada más cercana revela una ley muy interesante, el primero es siempre el último en el mismo (después de todo, los datos de la raíz) y después de la orden de recorrido del recorrido de la exposición de motivos.

Preorder traversal: [3], 0,1,2,6,5,4,8,7,9
postorden traversal: 2,1,0,4,5,7,9,8,6, [3]

Extracción de los datos de la raíz:

Preorden transversal (izquierda + derecha subárbol subárbol): 0,1,2,6,5,4,8,7,9
orden posterior (izquierdo + derecho subárbol subárbol): 2,1,0,4 , 5,7,9,8,6

Debido a que el subárbol izquierdo primero, así que esta vez antes de que el orden previo recorrido de la primera necesidad es la raíz del subárbol izquierdo, pero también sabemos que la raíz del subárbol izquierdo de recorrido de fin del último bit de datos en el subárbol izquierdo , marcamos esto:

Preorder traversal (izquierdo + derecho subárbol subárbol): [0], 1, 2 + 6,5,4,8,7,9
postorden (izquierdo + derecho subárbol subárbol): 2,1, [ 0] + 4,5,7,9,8,6

De esta manera se puede fácilmente subárbol izquierdo y subárbol derecho distingue aquí. Y luego se divide aún más.
Esto es todo? Por supuesto que no, de hecho, hay una pequeña trampa, sólo para el subárbol izquierdo nos distinguen como un ejemplo:

Preorder traversal: [0], 1,2
postorden traversal: 2,1, [0]

De acuerdo con el método anterior se puede saber en este momento para distinguir entre sub-árbol:

Preorder traversal (izquierdo + derecho subárbol subárbol): [1], 2 + NULL
postorden (izquierdo + derecho subárbol subárbol): 2, [1] + NULL

Sin embargo, este caso [2] no es un subárbol izquierdo (1,2 mayor raíz que 0), pero el subárbol derecho.
Esta situación se debe a los subárboles izquierdo y derecho en el que un espacio en blanco, en este momento la necesidad de una determinación sencilla (grande pequeño izquierda y derecha).
OK, puede el código:

//pre:前序遍历
//back:后序遍历
//length:数组长度
Tree* Fun3(const int *pre,const int *back,const int length){
    //当空指针或者数组长度为0时返回
    if(pre==NULL||back==NULL||length<=0)
        return NULL;
    
    //建立根节点
	Tree *head = new Tree();
	head->value=pre[0];
	head->left=head->right=NULL;
    
    //数组长度为1时,直接返回,因为没有子节点了
    if(length>1){
        //找到左右子树的分界点
        int index=0;
        while(index<length){
            if(pre[1]==back[index]){
                break;
            }
            ++index;
        }
        
        //判断是否是唯一子树
        if(index==length-2){
            //唯一子树需要判断为左子树还是右子树
            if(back[0]<head->val){
                head->left=Fun3(pre+1,back,index+1);
            }else{
                head->right=Fun3(pre+1, back, index+1);
            }
        }else{
            //左右子树均存在时,左边的为左子树,右边的为右子树
            head->left=Fun3(pre+1,back,index+1);
            head->right=Fun3(pre+index+2, back+index+1, length-index-2);
        }
    }
    
    return head;
}
Publicado 63 artículos originales · ganado elogios 73 · Vistas a 70000 +

Supongo que te gusta

Origin blog.csdn.net/jjwwwww/article/details/85848891
Recomendado
Clasificación