您的位置:首页 > Web前端

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

2014-04-27 20:28 323 查看
题目: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和编程之美


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: