Tree Recovery (known pre-order and middle-order and post-order traversal of binary trees)

topic

Little Valentine liked playing with binary trees very much. Her favorite game was constructing randomly looking binary trees with capital letters in the nodes.
This is an example of one of her creations:

                                           D

                                          / \

                                         /   \

                                        B     E

                                       / \     \

                                      /   \     \

                                     A     C     G

                                                /

                                               /

                                              F

To record her trees for future generations, she wrote down two strings for each tree: a preorder traversal (root, left subtree, right subtree) and an inorder traversal (left subtree, root, right subtree). For the tree drawn above the preorder traversal is DBACEGF and the inorder traversal is ABCDEFG.
She thought that such a pair of strings would give enough information to reconstruct the tree later (but she never tried it).

Now, years later, looking again at the strings, she realized that reconstructing the trees was indeed possible, but only because she never had used the same letter twice in the same tree.
However, doing the reconstruction by hand, soon turned out to be tedious.
So now she asks you to write a program that does the job for her!

Input
The input will contain one or more test cases.
Each test case consists of one line containing two strings preord and inord, representing the preorder traversal and inorder traversal of a binary tree. Both strings consist of unique capital letters. (Thus they are not longer than 26 characters.)
Input is terminated by end of file.

Output
For each test case, recover Valentine’s binary tree and print one line containing the tree’s postorder traversal (left subtree, right subtree, root).
Sample Input
DBACEGF ABCDEFG
BCAD CBAD
Sample Output
ACBFGED
CDAB

Title description:

It is to give the first-order traversal and the middle-order traversal of the binary tree, and let the traversal in the latter order.

Problem-solving ideas:

Let me talk about how the first, middle, and post-order traversal of the binary tree is established.
The operation of the first-order traversal of the binary tree is defined as follows:
if the binary tree is empty, then no operation; otherwise
(I) visit the root node;
(2) traverse the left child first Tree;
(3) Traverse the right subtree first.
The operation of middle-order traversal of a binary tree is defined as follows:
if the binary tree is empty, no operation; otherwise
(1) middle-order traversal of the left subtree;
(2) access to the root node;
(3) middle-order traversal of the right subtree.
The operation of post-order traversal of the binary tree is defined as follows:
if the binary tree is empty, no operation; otherwise
(1) post-order traversal of the left subtree;
(2) post-order traversal of the right subtree;
(3) visit the root node.
Pre-order traversal: visit the root node first, then visit the left subtree and right subtree in the previous order.
Middle-order traversal: left subtree, current node, right subtree.

According to the characteristics of pre-order and middle-order traversal, the following rule can be found:
each node of pre-order traversal is the root node of the current subtree. At the same time, taking the corresponding node as the boundary, the result of the in-order traversal will be divided into the left subtree and the right subtree.

Sample analysis:

Sample Input
DBACEGF ABCDEFG
Sample Output
ACBFGED

Pre-order: DBACEGF'D
' is the root node.
In post-order traversal, the root node is the last (ACBFGE D )
. In-order: ABCDEFG'D
' is the root node. Divide the string into two left and right subtrees.'D
' is the first Traversing the first element of the node in order, it can be seen that it divides the result of the middle order traversal into two parts,'ABC' and'EFG', namely the left subtree (ABC) and the right subtree (EFG).
In order: the ABC D EFG
find a left subtree (BAC) and the right subtree (EGF) the corresponding preorder traversal.
Pre-order: D BAC EGF
can take'D ' as the current root node, and then recurse sequentially, so that the traversal results of the left subtree and the right subtree can be restored in turn.

Diagram Treat
every tree as the simplest binary tree

Find the root node through the characteristics of pre-order and middle-order traversal and record s3[n-1+ss1] = s1[ss]; (because the root node of the post-order traversal is at the end of the current binary tree)
Insert picture description here

After recording the root node, the left and right subtrees are regarded as the simplest binary tree
kk(i, ss+1, n1, ss1);//left subtree
kk(ni-1, ss+i+1, n1+i +1, ss1+i);//right subtree

Insert picture description here

to sum up:

First find the root node, then find the left and right subtrees, and then the left and right subtrees, and finally realize it in turn through recursion
(in other words, always search for the root node)

Code:
Array implementation

#include <stdio.h>
#include <string.h>
char s1[30],s2[30],s3[30];

void kk(int l, int ss, int l1, int ss1)
{
    
    
	if(!l) //无子树
	return; 
	
	int i;
	for(i = 0; ; i++)
	{
    
    
		if(s1[ss] == s2[l1+i])//找到根结点 
		break;
	} 
	s3[l-1+ss1] = s1[ss];//记录后序遍历结果 
	kk(i, ss+1, l1, ss1);//左子树 
	kk(l-i-1, ss+i+1, l1+i+1, ss1+i);//右子树 
	
}
int main()
{
    
    
	int n;
	while(scanf("%s%s", s1, s2) != EOF)
	{
    
    
		n= strlen(s1);
		kk(n, 0, 0, 0);
		for(int i=0;i<n;i++)
		printf("%c",s3[i]);
		printf("\n");
	}
	return 0;
} 

Linked list implementation

#include <stdio.h>
#include <string.h>
#include <malloc.h>
typedef struct node
{
    
    
    char ch;
    struct node *left, *right;
}Node;         //定义节点的结构
 
node *creat(char *p, char *p1, int len)
{
    
    
    int k;
    if (!len)//出口//无子树
        return NULL;
    Node *head= (Node*)malloc(sizeof(Node));
    head -> ch = *p;
    char *p2;
    for (p2 = p1; p2 != NULL; p2++){
    
    
        if (*p2 == *p)    //找到根结点 
            break;
    }
    k = p2 - p1;
    head -> left = creat(p + 1, p1, k);    //左子树 
    head -> right = creat(p + k + 1, p2 + 1, len - k - 1);    //右子树
    return head;
}
 
void print(Node *head)    //输出序列
{
    
    
    if (head == NULL)
        return ;
    print(head -> left);
    print(head -> right);
    printf("%c",head -> ch);
}
 
int main()
{
    
    
    char p[30], p1[30];      //存储先序和中序遍历的序列
    Node *head;
    head = (Node*)malloc(sizeof(Node));
    while (scanf("%s %s",p,p1)!=EOF)
	{
    
    
        int len = strlen(p);
        head = creat(p, p1, len);
        print(head);
       printf("\n");
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_46703995/article/details/112465533