重建二叉树(剑指offer6、编程之美3.9)

来源:互联网 发布:面试php基础知识 编辑:程序博客网 时间:2024/06/07 12:11

题目:1.给出二叉树的前序和中序遍历序列,构建出这个二叉树;2.根据二叉树的中序和后序遍历序列,构建出这个二叉树;遍历序列中没有重复的结点值。

   问:假如遍历序列中含有相同的结点值时,如和求解?

1.根据前序和中序序列构建二叉树。思路:易知前序序列中的第一个结点即为二叉树的根结点,而此结点在中序序列中将二叉树的结点分为两部分,其左边部分即为左子树中的各个结点,其有边部分即为右子树中的各个结点,根据这些我们可以得到左右子树中分别有多少个结点,假设左子树中有left个结点,右子树中有right个结点,进而又可以将先序序列分为两部分,根结点后面的left个结点即为左子树中的结点,最后面的right个结点即为右子树中的结点。利用递归可以重复求解,最终得到我们期望的二叉树结果。

//根据二叉树前序和中序遍历构造二叉树BinaryTreeNode* constructBT(int* preorder, int* inorder, int length) {if (NULL == preorder || NULL == inorder || 0 >= length) {return NULL;}return constructBTByPreInOrder(preorder, preorder + length - 1, inorder,inorder + length - 1);}//根据二叉树前序和中序遍历构造二叉树BinaryTreeNode* constructBTByPreInOrder(int* startPreorder, int* endPreorder,int* startInorder, int* endInorder) {if (NULL == startPreorder || NULL == endPreorder || NULL == startInorder|| NULL == endInorder) {return NULL;}//创建根结点int rootValue = startPreorder[0];BinaryTreeNode* root = new BinaryTreeNode();root->m_nValue = rootValue;root->m_pLeftChild = NULL;root->m_pRightChild = NULL;//在中序序列中找到根结点int* rootInorder = startInorder;for (; rootInorder <= endInorder; ++rootInorder) {if (rootValue == *rootInorder) {break;}}//分别求得左右子树的结点数int leftChildLength = rootInorder - startInorder;int rightChildLength = endInorder - rootInorder;//构建左子树if (0 < leftChildLength) {root->m_pLeftChild = constructBTByPreInOrder(startPreorder + 1,startPreorder + leftChildLength, startInorder, rootInorder - 1);}//构建右子树if (0 < rightChildLength) {root->m_pRightChild = constructBTByPreInOrder(startPreorder + leftChildLength + 1, endPreorder,rootInorder + 1, endInorder);}return root;}

2.根据二叉树的中序和后序遍历序列,构造二叉树。思路:利用前面的思路,很容易得到下面这个结果。

//根据二叉树中序和后序遍历构造二叉树BinaryTreeNode* constructBT(int* inorder, int* postorder, int length) {if (NULL == inorder || NULL == postorder || 0 >= length) {return NULL;}return constructBTByInPostOrder(inorder, inorder + length - 1, postorder,postorder + length - 1);}BinaryTreeNode* constructBTByInPostOrder(int* startInorder, int* endInorder,int* startPostOrder, int* endPostOrder) {if (NULL == startInorder || NULL == endInorder || NULL == startPostOrder|| NULL == endPostOrder) {return NULL;}//根据后序遍历得到根结点int rootValue = endPostOrder[0];BinaryTreeNode* root = new BinaryTreeNode();root->m_nValue = rootValue;root->m_pLeftChild = NULL;root->m_pRightChild = NULL;//在中序序列中找根结点int* rootInorder = startInorder;for (; rootInorder <= endInorder; ++rootInorder) {if (rootValue == *rootInorder) {break;}}//分别计算左右子树中的结点数目int leftChildCount = rootInorder - startInorder;int rightChildCount = endInorder - rootInorder;//构建左右子树if (0 < leftChildCount) {root->m_pLeftChild = constructBTByInPostOrder(startInorder,rootInorder - 1, startPostOrder,startPostOrder + leftChildCount - 1);}//构建右孩子if (0 < rightChildCount) {root->m_pRightChild = constructBTByInPostOrder(rootInorder + 1,endInorder, startPostOrder + leftChildCount, endPostOrder - 1);}return root;}

测试代码

#include <stddef.h>#include <iostream>using namespace std;int main() {int n = 0;cout << "输入测试数据的组数:" << endl;cin >> n;while (n > 0) {cout << "输入序列长度:" << endl;int len = 0;cin >> len;int *x = new int[len];int *y = new int[len];cout << "输入先(中)序序列:" << endl;for (int i = 0; i < len; ++i) {cin >> x[i];}cout << "输入中(后)序序列:" << endl;for (int i = 0; i < len; ++i) {cin >> y[i];}BinaryTreeNode* binaryTreeNode = constructBT(x, y, len);cout << "二叉树前序遍历(递归):" << endl;preorderTravesal(binaryTreeNode);cout << endl;cout << "二叉树的后序遍历(递归):" << endl;postorderTravesal(binaryTreeNode);cout << endl;delete x;delete y;--n;}return 0;}


注:部分内容参考自剑指offer和编程之美


0 0
原创粉丝点击