剑指offer---面试题6重建二叉树

题目描述:

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。重建出二叉树,并输出根节点。二叉树的定义如下:
struct BinaryTreeNode
{
int m_nValue;
struct BinaryTreeNode * m_pLeft;
struct BinaryTreeNode * m_pRigth;
};


如上,前序遍历(1,2,4,7,3,5,6,8,),中序(4,7,2,1,5,3,8,6,)。后序遍历(7,4,2,5,8,6,3,1)

分析:

在二叉树的前序遍历中,第一个数字总是根节点,单在中序中,左子树的节点位于根节点的左侧,右子树在右侧。
可以用递归方法,完成分别构建左子树和右子树。


//已知前序和中序遍历,构造二叉树。
///

#include "stdafx.h"
#include <stdio.h>
#include <exception>
struct BinaryTreeNode
{
	int m_nValue;
	struct BinaryTreeNode * m_pLeft;
	struct BinaryTreeNode * m_pRigth;
};
BinaryTreeNode * ConstructCore(int *startPreorder,int *endPreorder,int *startInorder,int *endInorder)
{
	//the first node in preorder is the root node
	int rootValue=startPreorder[0];
	BinaryTreeNode *root = new BinaryTreeNode();
	root->m_nValue=rootValue;
	root->m_pLeft=root->m_pRigth=NULL;

	//end condition
	if(startPreorder==endPreorder)
	{
		if(*startPreorder==*endPreorder && startInorder==endInorder)
			return  root;
		else
			throw std::exception("invalid input");
	}
	//在中序遍历找到根节点的值
	int *rootInorder = startInorder;
	while(*rootInorder!=rootValue && rootInorder<=endInorder)
		rootInorder++;
	if(*rootInorder!=rootValue && rootInorder==endInorder)
		throw std::exception("invalid input!");

	int leftLength=rootInorder-startInorder;
	int *leftPreorderEnd = startPreorder+leftLength;
	if(leftLength>0)
	{
		root->m_pLeft = ConstructCore(startPreorder+1,leftPreorderEnd,startInorder,rootInorder-1);
	}
	if(leftLength<endPreorder-startPreorder)
		root->m_pRigth=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 0;
	return ConstructCore(preorder,preorder+length-1,inorder,inorder+length-1);

}


/test code

void PrintTreeNode(BinaryTreeNode *pNode)
{
	if(pNode!=NULL)
	{
		printf("this node value is : %d\n",pNode->m_nValue);
		if(pNode->m_pLeft != NULL)
            printf("value of its left child is: %d.\n", pNode->m_pLeft->m_nValue);
        else
            printf("left child is null.\n");

        if(pNode->m_pRigth != NULL)
            printf("value of its right child is: %d.\n", pNode->m_pRigth->m_nValue);
        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->m_pLeft!=NULL)
			PrintTree(pRoot->m_pLeft);
		if(pRoot->m_pRigth!=NULL)
			PrintTree(pRoot->m_pRigth);
	}

}

void DestoryTree(BinaryTreeNode *pRoot)
{
	if(pRoot!=NULL)
	{
		BinaryTreeNode * pLeft=pRoot->m_pLeft;
		BinaryTreeNode *pRight = pRoot->m_pRigth;
		delete pRoot;
		pRoot=NULL;
		DestoryTree(pLeft);
		DestoryTree(pRight);
	}
}

void Test(char *testName,int *preorder,int *inorder,int length)
{
	if(testName != NULL)
        printf("%s begins:\n", testName);

    printf("The preorder sequence is: ");
    for(int i = 0; i < length; ++ i)
        printf("%d ", preorder[i]);
    printf("\n");

    printf("The inorder sequence is: ");
    for(i = 0; i < length; ++ i)
        printf("%d ", inorder[i]);
    printf("\n");

    try
    {
        BinaryTreeNode* root = Construct(preorder, inorder, length);
        PrintTree(root);

        DestoryTree(root);
    }
    catch(std::exception& exception)
    {
        printf("Invalid Input.\n");
    }
}
// 普通二叉树
//              1
//           /     \
//          2       3  
//         /       / \
//        4       5   6
//         \         /
//          7       8
void 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
//     /
//    5
void 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
//                   \
//                    5
void 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   7
void 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(int argc, char* argv[])
{
	Test1();
	Test2();
    Test3();
    Test4();
    Test5();
    Test6();
    Test7();
	printf("Hello World!\n");
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值