剑指Offer面试题6[重建二叉树]

来源:互联网 发布:软件拉新方案 编辑:程序博客网 时间:2024/06/05 00:38

1.题目描述:

  输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

2. 相关知识:

2.1 树的相关概念:

  结点拥有的子树的个数成为结点的度,度为0的结点称为叶子或者终端结点,树中结点的最大层次称为树的深度

2.2 二叉树相关概念:

  二叉树的每个结点最多只有两颗子树,二叉树的第i层上最多有2i1个结点(i1),深度为k的二叉树之多有2k1个结点(k1),具有n个结点的完全二叉树的深度为log2n+1
  二叉树共有三种遍历方式,为笔试面试考点的重中之重,以下图为例。

  • 前序遍历(根-左-右):10-6-4-8-14-12-16
  • 中序遍历(左-根-右):4-6-8-10-12-14-16
  • 后序遍历(左-右-根):4-8-6-12-16-14-10

  另外,还有一种宽度优先遍历:从上到下,从左到右,如上图所示为:10-6-14-4-8-12-16

2.3 特殊的二叉树:

  • 二叉搜索树(Binary Search Tree),又名二叉排序树(Binary Sort Tree):左子结点总是小于或等于根结点,右子节点总是大于或等于根结点。上图的例子便是二叉搜索树。二叉搜索树中查找某结点的时间为O(log2(n))
  • 堆:分为最大堆(根节点最大)和最小堆(根结点最小)
  • 平衡二叉树:左子树和右子树的深度只差绝对值不超过1.
  • 红黑树:
  • 哈夫曼树:给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

3. 解答思路:

  根据前序遍历、中序遍历的特点,采用递归的方法分别重建出左右子树

4. 代码实现:

C语言版本

#include "stdafx.h"  #include <vector>  #include <stack>  #include <iostream>  #include <stdio.h>    #include <stdlib.h>  using namespace std;  //树的结构体struct BinaryTreeNode {    int                    value;     BinaryTreeNode*        pLeft;      BinaryTreeNode*        pRight; };void PrintTreeNode(BinaryTreeNode* pNode){    if(pNode != NULL)    {        printf("value of this node is: %d\n", pNode->value);        if(pNode->pLeft != NULL)            printf("value of its left child is: %d.\n", pNode->pLeft->value);        else            printf("left child is null.\n");        if(pNode->pRight != NULL)            printf("value of its right child is: %d.\n", pNode->pRight->value);        else            printf("right child is null.\n");    }    else    {        printf("this node is null.\n");    }    printf("\n");}void PrintTree(BinaryTreeNode* pRoot){    PrintTreeNode(pRoot);    if(pRoot != NULL)    {        if(pRoot->pLeft != NULL)            PrintTree(pRoot->pLeft);        if(pRoot->pRight != NULL)            PrintTree(pRoot->pRight);    }}//递归BinaryTreeNode* reConstructBinaryTree(int* startPreOdrer, int* endPreOrder, int* startInOrder, int* endInOrder){    //前序遍历    int rootValue = *startPreOdrer;    BinaryTreeNode* treeNode = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));    treeNode->value = rootValue;    treeNode->pLeft = NULL;    treeNode->pRight = NULL;    if (startPreOdrer == endPreOrder)    {        if (startInOrder ==  endInOrder && *startPreOdrer == *startInOrder)            return treeNode; //递归出口    }    //中序遍历    int* rootInOrder = startInOrder;    while (rootInOrder <= endInOrder && *rootInOrder != rootValue)    {        rootInOrder++;    }    int leftLength = rootInOrder - startInOrder;    int *leftPreOrderEnd = startPreOdrer + leftLength;    if (leftLength > 0)//重建左子树    {        treeNode->pLeft = reConstructBinaryTree(startPreOdrer + 1, leftPreOrderEnd, startInOrder, rootInOrder - 1);    }    if (endPreOrder - startPreOdrer - leftLength > 0)//重建右子树    {        treeNode->pRight = reConstructBinaryTree(leftPreOrderEnd + 1, endPreOrder, rootInOrder + 1, endInOrder);    }    return treeNode;}BinaryTreeNode* reConstruct(int* preOrder, int*inOrder, int length){    if (preOrder == NULL || inOrder == NULL || length < 0)        return NULL;    return reConstructBinaryTree(preOrder, preOrder + length - 1, inOrder, inOrder + length - 1);}int _tmain(int argc, _TCHAR* argv[]){    const int length = 8;    int preorder[length] = {1, 2, 4, 7, 3, 5, 6, 8};    int inorder[length] = {4, 7, 2, 1, 5, 3, 8, 6};     BinaryTreeNode* root= reConstruct(preorder, inorder, length);    PrintTree(root);    system("pause");    return 0;}

C++语言版本

// ex06_cpp.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <vector>  #include <stack>  #include <iostream>  #include <stdio.h>    #include <stdlib.h>  using namespace std;  struct TreeNode {    int val;    TreeNode *left;    TreeNode *right;    TreeNode(int x) : val(x), left(NULL), right(NULL) {}};class Solution {public:    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {        int length = pre.size();        if(length == 0)//递归出口            return NULL;        int rootValue = pre[0];//前序遍历root结点        TreeNode *node = new TreeNode(rootValue);        int p = 0;//指向中序遍历root结点        for(; p < length; p++) {            if (vin[p] == rootValue)                            break;        }        //先序左子树、右子树,中序左子树、右子树        vector<int> pre_left(pre.begin()+1, pre.begin()+p+1);        vector<int> pre_right(pre.begin()+p+1, pre.end());        vector<int> in_left(vin.begin(), vin.begin()+p);        vector<int> in_right(vin.begin()+p+1, vin.end());        node->left = reConstructBinaryTree(pre_left, in_left);        node->right = reConstructBinaryTree(pre_right, in_right);        return node;    }};int _tmain(int argc, _TCHAR* argv[]){    const int length = 8;      int preorder[8] = { 1, 2, 4, 7, 3, 5, 6, 8 };      int inorder[8] = { 4, 7, 2, 1, 5, 3, 8, 6 };      vector<int> pre_vec(preorder,preorder+length);    vector<int> in_vec(inorder,inorder+length);    Solution s;      TreeNode* node = s.reConstructBinaryTree(pre_vec,in_vec);    return 0;}
阅读全文
0 0
原创粉丝点击