重建二叉树

来源:互联网 发布:js异步同步的区别 简书 编辑:程序博客网 时间:2024/05/21 21:48

根据二叉树的前序遍历和中序遍历的结果,重建这棵树。

分析:前序遍历的每一个节点,都是当前子树的根节点。同时,以对应的节点为边界,就会把中序遍历的结果分为左子树和右子树。

前序:a b d c e f

          “a是根节点

中序:d b a e c f

          “a是根节点,把字符串分成左右两个子树

       "a"是前序遍历节点中的第一个元素,可以看出,它把中序遍历的结果分成"db"和'ecf"这两部分。

       如果能够找到前序遍历中对应的左子树和右子树,就可以把"a"作为当前的根节点,然后依次递归下去,这样就能够依次恢复左子树和右子树的遍历结果。

上代码:

#include <iostream>using namespace std;#define TREELEN6structNODE{NODE* pLeft;NODE* pRight;char chValue;};void rebuild(char* pPreOrder, char* pInOrder, int nTreeLen, NODE** pRoot){//检查边界条件if (pPreOrder == NULL || pInOrder == NULL){return;}//获取前序遍历的第一个结点NODE* pTemp = new NODE;pTemp->chValue = *pPreOrder;pTemp->pLeft = NULL;pTemp->pRight = NULL;//如果结点为空,把当前结点复制到根节点if (*pRoot == NULL){*pRoot = pTemp;}//如果当前长度为1,那么已经是最后一个节点if (nTreeLen == 1){return;}//寻找子树长度char* pOrgInorder = pInOrder;char* pLeftEnd = pInOrder;int nTempLen = 0;//寻找左子树的结尾if (*pPreOrder != *pLeftEnd){if (pPreOrder == NULL || pLeftEnd == NULL){return;}nTempLen++;//记录临时长度,以免溢出if (nTempLen > nTreeLen){exit(-1);}pLeftEnd++;}//寻找左子树长度int pLeftLen = 0;pLeftLen = (int)(pLeftEnd - pOrgInorder);//寻找右子数长度int pRightLen = 0;pRightLen = (int)(nTreeLen - pLeftLen - 1);//重建左子树if (pLeftLen > 0){rebuild(pPreOrder+1, pInOrder, pLeftLen, &((*pRoot)->pLeft));}//重建右子树if (pRightLen > 0){rebuild(pPreOrder+pLeftLen+1, pInOrder+pLeftLen+1, pRightLen, &((*pRoot)->pRight));}}int main(){char szPreOrder[TREELEN] = {'a', 'b', 'd', 'c', 'e', 'f'};char szInOrder[TREELEN] = {'d', 'b', 'a', 'e', 'c', 'f'};NODE* pRoot = NULL;rebuild(szPreOrder, szInOrder, TREELEN, &pRoot);}


 

原创粉丝点击