剑指offer:6-重建二叉树

来源:互联网 发布:一分钟心理学 知乎 编辑:程序博客网 时间:2024/06/06 04:01

二叉树的遍历方式:前序、中序和后序。每种遍历均有递归和循环两种不同方法。递归实现要比循环简洁。


直接上代码:

二叉树节点结构:

(下面参考原书代码)

//BinaryTreeNode.h#ifndef BINARY_TREE_NODE_H#define BINARY_TREE_NODE_Hstruct BinaryTreeNode{int nValue;BinaryTreeNode *pLeftChild;BinaryTreeNode *pRightChild;};#endif

//BinaryTreeOperation.h#ifndef BINARY_TREE_OPERATION_H#define BINARY_TREE_OPERATION_H#include "BinaryTreeNode.h"//构造二进制树节点BinaryTreeNode *CreateBinaryTreeNode(int value);//连接树节点void ConnectTreeNodes(BinaryTreeNode *pParent,BinaryTreeNode *pLeftChild,BinaryTreeNode *pRightChild);//打印树节点void PrintTreeNode(BinaryTreeNode *pNode);//打印树void PrintTree(BinaryTreeNode *pRoot);//销毁树void DestroyTree(BinaryTreeNode *pRoot);#endif

//BinaryTreeOperation.cpp#include "BinaryTreeOperation.h"#include <iostream>using namespace std;//构造二进制树节点BinaryTreeNode *CreateBinaryTreeNode(int value){BinaryTreeNode *pNode = new BinaryTreeNode();pNode->nValue = value;pNode->pLeftChild = NULL;pNode->pRightChild = NULL;return pNode;}//连接树节点void ConnectTreeNodes(BinaryTreeNode *pParent,BinaryTreeNode *pLeftChild,BinaryTreeNode *pRightChild){if (pParent != NULL){pParent->pLeftChild = pLeftChild;pParent->pRightChild = pRightChild;}}//打印树节点void PrintTreeNode(BinaryTreeNode *pNode){if (pNode != NULL){cout << "value of this node is: " << pNode->nValue << endl;if (pNode->pLeftChild != NULL)cout << "value of its left child is: " << pNode->pLeftChild->nValue << endl;elsecout << "its left child is null.\n";if(pNode->pRightChild != NULL)cout << "value of its right child is: " << pNode->pRightChild->nValue << endl;elsecout << "its right child is null.\n";}elsecout << "this node is null.\n";cout << endl;}//打印树void PrintTree(BinaryTreeNode *pRoot){PrintTreeNode(pRoot);if (pRoot != NULL){if (pRoot->pLeftChild != NULL)PrintTree(pRoot->pLeftChild);if(pRoot->pRightChild != NULL)PrintTree(pRoot->pRightChild);}}//销毁树void DestroyTree(BinaryTreeNode *pRoot){if (pRoot != NULL){BinaryTreeNode *pLeft = pRoot->pLeftChild;BinaryTreeNode *pRight = pRoot->pRightChild;delete pRoot;pRoot = NULL;DestroyTree(pLeft);DestroyTree(pRight);}}

//main.cpp#include "BinaryTreeNode.h"#include "BinaryTreeOperation.h"#include <iostream>#include <exception>using namespace std;BinaryTreeNode *ConstructCore(int *startPreorder,int *endPreorder,int *strartInorder,int *endInorder){//前序遍历序列的第一个元素是根节点的值.int rootValue = startPreorder[0];BinaryTreeNode *root = new BinaryTreeNode();root->nValue = rootValue;root->pLeftChild = root->pRightChild = NULL;if (startPreorder == endPreorder){if(strartInorder == endInorder && *startPreorder == *strartInorder)return root;else throw exception("Invalid input!");}//在中序遍历中找到根节点的值.int *rootInorder = strartInorder;while(rootInorder <= endInorder && *rootInorder != rootValue)++rootInorder;if(rootInorder == endInorder && *rootInorder != rootValue)throw exception("Invalid input.");int leftLength = rootInorder - strartInorder;int *leftPreorderEnd = startPreorder + leftLength;//若左子树长度大于零,则存在左子树,构建左子树if (leftLength > 0)root->pLeftChild = ConstructCore(startPreorder + 1,leftPreorderEnd,strartInorder,rootInorder - 1);//若左子树长度小于总长度,则存在右子树,构建右子树if(leftLength < endPreorder - startPreorder)root->pRightChild = ConstructCore(leftPreorderEnd + 1,endPreorder,rootInorder+1,endInorder);return root;}BinaryTreeNode *Construct(int *preorder,int *inorder,int length){if(preorder == NULL ||inorder == NULL || length <= 0)return NULL;return ConstructCore(preorder,preorder + length -1,inorder,inorder + length - 1);}//=========================测试代码===========================void Test(char *testName,int *preorder,int *inorder,int length){if(testName != NULL)cout << "begins: " << testName << endl;cout << "the preorder sequence is: ";for (int i = 0;i < length;++i)cout << preorder[i] << " ";cout << endl << "the inorder sequence is: ";for (int i = 0;i < length;++i)cout << inorder[i] << " ";cout << endl;try{BinaryTreeNode *root = Construct(preorder,inorder,length);PrintTree(root);DestroyTree(root);}catch (exception& exception){cout << "Invalid Input.\n";}//cout << endl;}// 普通二叉树//              1//           /     \//          2       3  //         /       / \//        4       5   6//         \         ///          7       8void Test1(){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};Test("Test1", preorder, inorder, length);}// 所有结点都没有右子结点//            1//           / //          2   //         / //        3 //       ///      4//     ///    5void Test2(){const int length = 5;int preorder[length] = {1, 2, 3, 4, 5};int inorder[length] = {5, 4, 3, 2, 1};Test("Test2", preorder, inorder, length);}// 所有结点都没有左子结点//            1//             \ //              2   //               \ //                3 //                 \//                  4//                   \//                    5void Test3(){const int length = 5;int preorder[length] = {1, 2, 3, 4, 5};int inorder[length] = {1, 2, 3, 4, 5};Test("Test3", preorder, inorder, length);}// 树中只有一个结点void Test4(){const int length = 1;int preorder[length] = {1};int inorder[length] = {1};Test("Test4", preorder, inorder, length);}// 完全二叉树//              1//           /     \//          2       3  //         / \     / \//        4   5   6   7void Test5(){const int length = 7;int preorder[length] = {1, 2, 4, 5, 3, 6, 7};int inorder[length] = {4, 2, 5, 1, 6, 3, 7};Test("Test5", preorder, inorder, length);}// 输入空指针void Test6(){Test("Test6", NULL, NULL, 0);}// 输入的两个序列不匹配void Test7(){const int length = 7;int preorder[length] = {1, 2, 4, 5, 3, 6, 7};int inorder[length] = {4, 2, 8, 1, 6, 3, 7};Test("Test7: for unmatched input", preorder, inorder, length);}int main(){Test1();Test2();Test3();Test4();Test5();Test6();Test7();return 0;}

运行结果如下:



最后构建的二叉树如下所示:





原创粉丝点击