前序+ 中序 中序+后序 生成二叉树

10 篇文章 0 订阅
**package com.zzw.leetcode;

import java.util.ArrayList;
import java.util.List;

/**
 * @PACKAGE_NAME: com.zzw.leetcode
 * @NAME: Ergodic
 * @USER: zhaozhenwei
 * @DATE: 2021/7/22
 * @TIME: 6:15 下午
 * @Description:
 **/
public class Ergodic {
    static TreeNode root;

    static {
        TreeNode treeNode1 = new TreeNode(1);
        TreeNode treeNode2 = new TreeNode(2);
        TreeNode treeNode3 = new TreeNode(3);
        TreeNode treeNode4 = new TreeNode(4);
        TreeNode treeNode5 = new TreeNode(5);
        TreeNode treeNode6 = new TreeNode(6);
        TreeNode treeNode7 = new TreeNode(7);
        TreeNode treeNode8 = new TreeNode(8);
        TreeNode treeNode9 = new TreeNode(9);
        TreeNode treeNode10 = new TreeNode(10);
        TreeNode treeNode11 = new TreeNode(11);
        treeNode1.left = treeNode2;
        treeNode1.right = treeNode3;
        treeNode2.left = treeNode4;
        treeNode4.right = treeNode5;
        treeNode5.left = treeNode6;
        treeNode5.right = treeNode7;
        treeNode3.left = treeNode8;
        treeNode3.right = treeNode9;
        treeNode9.left = treeNode10;
        treeNode10.right = treeNode11;

        root = treeNode1;
    }

    static TreeNode createTreeByPreAndMid(int[] preorder, int[] inorder) {
        if (preorder == null || inorder == null || preorder.length != inorder.length) {
            return null;
        }
        return createTreeByPreAndMid(preorder, inorder, 0, preorder.length - 1, 0, inorder.length - 1);
    }

    static TreeNode createTreeByPreAndMid(int[] pre, int[] mid, int start0, int end0, int start1, int end1) {
        if (start0 > end0 || start1 > end1) {
            return null;
        }
        // 获取当前子树的根节点
        int rootNum = pre[start0];
        TreeNode root = new TreeNode(rootNum);
        // 通过根节点将前序遍历、中序遍历序列切成左右两个部分
        // 1.找到根节点在中序遍历中的位置(左子树的长度)
        int len = 0;
        for (int i = start1; i < end1; i++) {
            if (rootNum == mid[i]) {
                break;
            }
            len++;
        }

        // 2.将前序、中序遍历切分成两个部分
        // 前序 左子树
        int start00 = start0 + 1;
        int end00 = start0 + len;
        // 前序 右子树
        int start01 = start0 + len + 1;
        int end01 = end0;

        // 中序 左子树
        int start10 = start1;
        int end10 = start1 + len - 1;

        // 中序右子树
        int start11 = start1 + len + 1;
        int end11 = end1;

        // 使用左右两个部分递归调用本方法获取当前子树的左右节点
        root.left = createTreeByPreAndMid(pre, mid, start00, end00, start10, end10);
        root.right = createTreeByPreAndMid(pre, mid, start01, end01, start11, end11);
        return root;
    }


    static TreeNode createTreeByMidAndPost(int[] mid, int[] post) {
        if (mid == null || post == null || mid.length != post.length) {
            return null;
        }
        return createTreeByMidAndPost(mid, post, 0, mid.length - 1, 0, post.length - 1);
    }

    static TreeNode createTreeByMidAndPost(int[] mid, int[] post, int start0, int end0, int start1, int end1) {
        // 判断当前是否存在数据
        if (start0 > end0 || start1 > end1) {
            return null;
        }
        // 找到后续遍历中的最后一个元素,该元素是当前子树的根节点
        int root = post[end1];
        TreeNode treeNode = new TreeNode(root);

        // 找到后续遍历最后一个元素在中序遍历中的位置,以找到的元素距离中序遍历结果的第一个元素的具体为主
        int len = 0;
        for (int i = start0; i < end0; i++) {
            if (root == mid[i]) {
                break;
            }
            len++;
        }

        // 通过在中序遍历中找到的位置将中序遍历分成两个部分,不包含找到元素
        // 中序遍历 左子树部分
        int start00 = start0;
        int end00 = start00 + len - 1;
        // 中序遍历 右子树部分
        int start01 = start0 + len + 1;
        int end01 = end0;

        // 通过中序遍历中左右两个字序列的长度将后续遍历也分成两个部分,不包含最后一个元素。
        // 后续遍历左子树
        int start10 = start1;
        int end10 = start1 + len - 1;

        int start11 = start1 + len;
        int end11 = end1 - 1;

        // 使用中序遍历后续遍历集合被分成左右两部分的集合各调用一次本方法
        treeNode.left = createTreeByMidAndPost(mid, post, start00, end00, start10, end10);
        treeNode.right = createTreeByMidAndPost(mid, post, start01, end01, start11, end11);

        return treeNode;
    }

    public static void main(String[] args) {
        List<Integer> result = new ArrayList<>();
        int[] pre = {1, 2, 4, 5, 6, 7, 3, 8, 9, 10, 11};
        int[] mid = {4, 6, 5, 7, 2, 1, 8, 3, 10, 11, 9};
        int[] post = {6, 7, 5, 4, 2, 8, 11, 10, 9, 3, 1};

        TreeNode treeNode = createTreeByPreAndMid(pre, mid);
        postOrderTraversal(treeNode, result);
        System.out.println(result);
    }

    static void preorderTraversal(TreeNode treeNode, List<Integer> resut) {
        if (null == treeNode) {
            return;
        }
        resut.add(treeNode.val);
        preorderTraversal(treeNode.left, resut);
        preorderTraversal(treeNode.right, resut);
    }

    static void middleOrderTraversal(TreeNode treeNode, List<Integer> resut) {
        if (null == treeNode) {
            return;
        }
        middleOrderTraversal(treeNode.left, resut);
        resut.add(treeNode.val);
        middleOrderTraversal(treeNode.right, resut);
    }

    static void postOrderTraversal(TreeNode treeNode, List<Integer> resut) {
        if (null == treeNode) {
            return;
        }
        postOrderTraversal(treeNode.left, resut);
        postOrderTraversal(treeNode.right, resut);
        resut.add(treeNode.val);
    }

}
**

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是用 C 语言设计的程实现任意输入+生成唯一的二叉树,并打印其后列的功能: ```c #include <stdio.h> #include <stdlib.h> //定义二叉树结构体 typedef struct TreeNode { char data; //节点数据 struct TreeNode* left; //左孩子指针 struct TreeNode* right; //右孩子指针 } TreeNode; //根据生成叉树 TreeNode* createTree(char* preorder, char* inorder, int size) { if (size <= 0) { //列为空 return NULL; } TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode)); //创建根节点 root->data = *preorder; //根节点的值为遍历列的第一个元素 int pos = 0; while (pos < size && inorder[pos] != root->data) { //在遍历找到根节点的位置 pos++; } if (pos == size) { //无法找到根节点 printf("Error: Invalid Input!\n"); return NULL; } root->left = createTree(preorder + 1, inorder, pos); //递归构造左子树 root->right = createTree(preorder + pos + 1, inorder + pos + 1, size - pos - 1); //递归构造右子树 return root; } //后遍历二叉树并打印节点值 void postorder(TreeNode* root) { if (root == NULL) { //树为空 return; } postorder(root->left); //后遍历左子树 postorder(root->right); //后遍历右子树 printf("%c ", root->data); //输出当节点的值 } //主函数 int main() { char preorder[] = {'A', 'B', 'D', 'E', 'C', 'F', 'G'}; //遍历列 char inorder[] = {'D', 'B', 'E', 'A', 'F', 'C', 'G'}; //遍历列 int size = sizeof(preorder) / sizeof(preorder[0]); //列长度 TreeNode* root = createTree(preorder, inorder, size); //生成叉树 if (root != NULL) { //二叉树生成成功 printf("Postorder: "); postorder(root); //后遍历并打印二叉树 printf("\n"); } return 0; } ``` 程的思路是:根据遍历列来构造二叉树,然后后遍历二叉树并打印节点值。程用到了递归的思想,具体解释如下: 1. 定义二叉树结构体 ```c typedef struct TreeNode { char data; //节点数据 struct TreeNode* left; //左孩子指针 struct TreeNode* right; //右孩子指针 } TreeNode; ``` 定义一个包含节点数据、左孩子指针和右孩子指针的结构体,表示二叉树的节点。 2. 根据生成叉树 ```c TreeNode* createTree(char* preorder, char* inorder, int size) { if (size <= 0) { //列为空 return NULL; } TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode)); //创建根节点 root->data = *preorder; //根节点的值为遍历列的第一个元素 int pos = 0; while (pos < size && inorder[pos] != root->data) { //在遍历找到根节点的位置 pos++; } if (pos == size) { //无法找到根节点 printf("Error: Invalid Input!\n"); return NULL; } root->left = createTree(preorder + 1, inorder, pos); //递归构造左子树 root->right = createTree(preorder + pos + 1, inorder + pos + 1, size - pos - 1); //递归构造右子树 return root; } ``` 在此函数,首先判断列是否为空,如果为空则返回 NULL。然后创建一个根节点,并将根节点的值设为遍历列的第一个元素。接着在遍历找到根节点的位置,如果无法找到根节点,则输出错误提示并返回 NULL。然后递归构造左子树和右子树,最后返回根节点。 3. 后遍历二叉树并打印节点值 ```c void postorder(TreeNode* root) { if (root == NULL) { //树为空 return; } postorder(root->left); //后遍历左子树 postorder(root->right); //后遍历右子树 printf("%c ", root->data); //输出当节点的值 } ``` 该函数用于后遍历二叉树并打印节点值。首先判断树是否为空,如果为空则返回。然后递归后遍历左子树和右子树,最后打印当节点的值。 4. 主函数 ```c int main() { char preorder[] = {'A', 'B', 'D', 'E', 'C', 'F', 'G'}; //遍历列 char inorder[] = {'D', 'B', 'E', 'A', 'F', 'C', 'G'}; //遍历列 int size = sizeof(preorder) / sizeof(preorder[0]); //列长度 TreeNode* root = createTree(preorder, inorder, size); //生成叉树 if (root != NULL) { //二叉树生成成功 printf("Postorder: "); postorder(root); //后遍历并打印二叉树 printf("\n"); } return 0; } ``` 在主函数,定义遍历列和遍历列,计算列长度,然后调用 createTree 函数生成叉树,如果二叉树生成成功,则后遍历并打印二叉树

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值