Algorithm-Recovery of Binary Tree

1. The nature of binary trees

Binary tree is an extremely important data structure. The mastery of it reflects the mastery of our data structure, especially when some large companies interview programmers who are not from a professional class, they will have some problems similar to binary tree recovery. Come and test us.

Let’s take a look at this binary tree first. Let’s take him as an example

			   1
			   
		2			  3
		
   4		5    6		    7

Look at the traversal rules again:

	前序遍历:根-左-右  
	中序遍历:左-根-右
	后续遍历:左-右-根

Traverse results:

	前序遍历:1 2 4 5 3 6 7
	中序遍历:4 2 5 1 6 3 7
	后续遍历:4 5 2 6 7 3 1

Different ways of traversing binary trees have their own characteristics, mainly as follows:

	前序遍历:第一个元素是根节点
	中序遍历:根节点左侧为左子树,右侧为右子树
	后续遍历:最后一个元素是根节点

2. Restore the binary tree according to the pre-order and middle-order traversal results

2.1 Manual reasoning

According to the characteristics of the pre-order traversal and the middle-order traversal of the binary tree, we can use the recursive method to restore the tree

	前序遍历:1 2 4 5 3 6 7
	中序遍历:4 2 5 1 6 3 7

Taking the above example, according to the preorder traversal, we know that the root node is 1, the left subtree element is 4 2 5, and the right subtree element is 6 3 7

According to the results of pre-order traversal and post-order traversal, we also know that the results of pre-order and middle-order traversal of the left subtree are:

	前序遍历:2 4 5
	中序遍历:4 2 5

Therefore, we know that the left son of the root node is the root node of the left subtree, which is 2

The tree we constructed to this step looks like this

	1
2

Similarly, the result set of the preorder and postorder traversal of the right subtree is:

	前序遍历:3 6 7
	中序遍历:6 3 7

We came to the conclusion that 3 is the root node of the right subtree of the root node. So we constructed such a tree

	1
2       3

Then, we recursively construct the tree and get a complete binary tree.

It can be seen that the key to the problem is to find the root node, determine the left and right subtrees, and restore the left and right subtrees recursively!

2.2 Java implementation

    /**
     * 
     * @param preOrder 先序遍历结果集
     * @param preStart 本段先序遍历起始位置
     * @param preEnd 本段先序遍历终止位置
     * @param inOrder 中序遍历结果集
     * @param inStart 本段中序遍历起始位置
     * @param inEnd 本段中序遍历终止位置
     * @return 构造的二叉树
     */
    public TreeNode rebuildTreeFromPreIn(int[] preOrder,int preStart,int preEnd,int[] inOrder,int inStart,int inEnd){
    
    
        if(preStart>preEnd||inStart>inEnd){
    
    
            return null;
        }
        int headVal=preOrder[preStart];
        TreeNode head=new TreeNode(headVal);
        int leftSize=0;//左子树大小
        for(int i=inStart;i<=inEnd;i++){
    
    //遍历当前中序遍历的结果,找到根节点,划分左右子树
            if(inOrder[i]==headVal){
    
    //找到当前根节点位置
                break;
            }
            leftSize++;//当前左子树大小
        }
        
		//注意左子树前序遍历的起始位置为当前左子树起始位置+1,终止位置为当前左子树起始位置+左子树大小
		//左子树中序遍历起始位置为中序遍历的左子树起始位置,结束位置为原来根节点位置的前一个位置,也就是inStart+leftSize-1     
   		head.left=rebuildTreeFromPreIn(preOrder,preStart+1,preStart+leftSize,inOrder,inStart,inStart+leftSize-1);
        head.right=rebuildTreeFromPreIn(preOrder,preStart+leftSize+1,preEnd,inOrder,inStart+leftSize+1,inEnd);
        return head;
    }

3. Restore the binary tree based on the results of the middle and post-order traversal

The way to restore the binary tree according to the middle order and the post order traversal is almost the same as the method in 2. The difference is that the head of the post order traversal is the element at the last position of the post order traversal.

    /**
     *
     * @param inOrder 中序遍历结果集
     * @param inStart 本段中序遍历起始位置
     * @param inEnd 本段中序遍历终止位置
     * @param postOrder 后续遍历结果集合
     * @param postStart 本段后序遍历起始位置
     * @param postEnd 本段后序遍历终止位置
     * @return
     */
    public TreeNode rebuildTreeFromInPost(int inOrder[],int inStart,int inEnd,int postOrder[],int postStart,int postEnd){
    
    
        if(inStart>inEnd||postStart>postEnd){
    
    
            return null;
        }
        int headVal=postOrder[postEnd];
        TreeNode head=new TreeNode(headVal);
        int leftSize=0;//左子树元素个数
        for (int i=inStart;i<=inEnd;i++){
    
    
            if(inOrder[i]==headVal){
    
    //从中序遍历找到根节点,左边为左子树,右边为右子树
                break;
            }
            leftSize++;
        }
        head.left=rebuildTreeFromInPost(inOrder,inStart,inStart+leftSize,postOrder,postStart,postStart+leftSize-1);
        head.right=rebuildTreeFromInPost(inOrder,inStart+leftSize+1,inEnd,postOrder,postStart+leftSize,postEnd-1);
        return head;
    }

Guess you like

Origin blog.csdn.net/qq_23594799/article/details/105456254