二叉树的应用 c++ 实现

1.判断两颗二叉树是否相同(左右子树不能旋转):可以采用递归方法实现

struct binaryNode {
	int m_ivalue;
	binaryNode* m_pLeft;
	binaryNode* m_pRight;
};
bool _isEqual(binaryNode* node1, binaryNode*node2)
{
	if (node1 == NULL&&node2 == NULL)
		return 1;
	if (!node1 || !node2)
		return 0;
	if (node1->m_ivalue == node2->m_ivalue)
		return _isEqual(node1->m_pLeft, node2->m_pLeft) && _isEqual(node1->m_pRight, node2->m_pRight);
	else
		return 0;
}
如果左右子树可以旋转,只需要修改以上返回递归条件部分:
return (_isEqual(node1->m_pLeft, node2->m_pLeft) && _isEqual(node1->m_pRight, node2->m_pRight))|| (_isEqual(node1->m_pLeft, node2->m_pRight) && _isEqual(node1->m_pRight, node2->m_pLeft));

2.求二叉树的深度

输入一棵二叉树的根节点,求该树的深度。从根节点到叶子结点以此经过的结点形成树的一条路径,最长路径的长度为树的深度。本质还是二叉树遍历,需要求出左右子树的深度,才能求出根节点的深度,使用后序遍历。

truct SBinaryTreeNode {
	int m_nValue;
	SBinaryTreeNode* m_pLeft;
	SBinaryTreeNode* m_pRight;
};
int tree_height(SBinaryTreeNode* root)
{
	int left, right;
	if (root == NULL)
		return -1;
	else
	{
		left = tree_height(root->m_pLeft) + 1;
		right = tree_height(root->m_pRight)+1;
		return (left > right) ? left : right;
	}
}

3.求二叉树中结点的最大距离

定义:父子结点之间的连线是双向的,距离为两结点之间边的个数,求一棵二叉树中距离最远的两个结点之间的距离。

这个问题的核心是,情况A和B需要不同的信息:A需要子树的最大深度,B需要子树的最远距离。只要函数能在一个结点同时计算及传回这两个信息。

struct node
{
	int value;
	struct node* pLeft;
	struct node* pRight;
};

struct result
{
	int nMaxdistance;
	int nMaxdepth;
};
result GetMaximumDistance(node* root)
{
	if (!root)
	{
		result empty = {0,-1};
		return empty;
	}
	result lhs = GetMaximumDistance(root->pLeft);
	result rhs = GetMaximumDistance(root->pRight);
	result res;
	res.nMaxdepth = max(lhs.nMaxdepth+1,rhs.nMaxdepth+1);
	res.nMaxdistance = max(max(lhs.nMaxdistance,rhs.nMaxdistance),lhs.nMaxdepth+rhs.nMaxdepth+2);
	return res;
}

nMaxDepth就是左子树和右子树的深度加1.nMaxDistance取A和B情况的最大值。

4.一棵二叉树每个结点包含一个整数,求此路径上所有结点之和为给定值(不必须从根节点开始)

案例:5,则2+3-4+3+1+2这条路径包含多个满足条件的子路径。(先序遍历)

struct TreeNode
{
	int data;
	struct TreeNode* left;
	struct TreeNode* right;
};
void printbuffer(vector<int> buffer,int level,int i2) 
{
	for (int i = level; i <= i2; i++)
		cout << buffer[i] << " ";
	cout << endl;
}
void findSum(TreeNode* head, int sum, vector<int>buffer, int level)
{
	if (head == NULL)
		return;
	int tmp = sum;
	buffer.push_back(head->data);
	for (int i = level; i > -1; i--)
	{
		tmp -= buffer[i];
		if (tmp == 0)
			printbuffer(buffer,i,level);
	}
	findSum(head->left,sum,buffer,level+1);
	buffer.pop_back();
	level -= -1;
	findSum(head->right,sum,buffer,level+1);
}

5.由遍历序列构造二叉树

由二叉树的先序遍历和中序遍历可以确定一棵二叉树。由二叉树的中序遍历和后序遍历可以确定一棵二叉树。(由二叉树的先序遍历和后序遍历是无法唯一确定一棵二叉树)

6.输入某二叉树的前序遍历和中序遍历的结果,请重新建出该二叉树。假设输入的前序遍历和中序遍历的结果都不含重复数字。前序遍历{1,2,4,7,3,5,6,8}中序遍历{4,7,2,1,5,3,8,6},重建二叉树并输出他的后序遍历。

思路:在二叉树的前序遍历序列中,第一个数字总是树的根结点的值.但在中序遍历序列中.根结点的值在序列的中间.左子树的结点的值位于根结点的值的左边,而右子树的结点点的值位于根结点的值的右边·因此我们通过扫描中序遍历序列.可以找到根结点的值.然后可以得出其左子树结点集与右子树结点集,也即得到了其左、右子树的前序遍历序列和中序遍历序列。我们可以用同样的方法分别去构建左右子树,本题可以用递归的方法来完成。

struct BinaryTreeNode {
	int m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
};
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);
}

BinaryTreeNode* ConstructCore(int* startPreorder, int* endPreorder, int * startInorder, int *endInorder)
{
	//前序遍历序列的第一个数字是根节点的值
	int rootValue = startPreorder[0];
	BinaryTreeNode* root = new BinaryTreeNode();  //建立结点
	root->m_nValue = rootValue;
	root->m_pLeft = root->m_pRight = NULL;
	if (startPreorder == endPreorder) //边界条件
	{
		if (startInorder == endInorder&&*startPreorder == *endPreorder)
			return root;
		else
			throw std::exception("invalid input.");
	}
	//在中序遍历中找到根节点的值
	int *rootInorder = startInorder;
	while (rootInorder <= endInorder&&*rootInorder != rootValue)
		++rootInorder;
	if (rootInorder == endInorder&&*rootInorder != rootValue)
		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_pRight = ConstructCore(leftPreorderEnd+1,endPreorder,rootInorder+1,endInorder);
	}
	return root;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值