判断二叉树是否是平衡二叉树
可以分两步实现。第一步先遍历二叉树中的每一个结点node,调用height()求出该结点的左子树高度height(node.left) 和 右子树高度 height(node.right)。根据左右子树的高度差是否满足其绝对值不超过1,第二步看左子树和右子树是否平衡(子问题),判断该树是否为平衡二叉树。
int IsBalanceTree(BTreeNode *pRoot)
{
if (pRoot == NULL)
return 1;
int left = IsBalanceTree(pRoot->pLeft);
if (left == 0)
return 0;
int right = IsBalanceTree(pRoot->pRight);
if (right == 0)
return 0;
int leftH = TreeHeightR(pRoot->pLeft);
int rightH = TreeHeightR(pRoot->pRight);
if ((leftH - rightH) <= 1 && (leftH - rightH) >= -1)
{
return 1;
}
else
{
return 0;
}
}
- 求二叉树中最远的两个结点间的距离
计算一个二叉树的最大距离有两个情况:
情况A: 路径经过左子树的最深节点,通过根节点,再到右子树的最深节点。
情况B: 路径不穿过根节点,而是左子树或右子树的最大距离路径,取其大者
对于情况A来说,只需要知道左右子树的深度,然后加起来即可。
对于情况B来说,需要知道左子树的最远距离,或者右子树的最远距离。
只需要计算这两种情况的路径距离,并取其最大值,就是该二叉树的最大距离。
//求二叉树的高度
int TreeHeightR(BTreeNode *pRoot)
{
if (pRoot == NULL)
return 0;
int leftH = TreeHeightR(pRoot->pLeft);
int rightH = TreeHeightR(pRoot->pRight);
return leftH > rightH ? (leftH + 1) : (rightH + 1);
}
int Max(int a, int b, int c)
{
if (a > b&&a > c)
return a;
if (b > a&&b > c)
return b;
return c;
}
int FarDistance(BTreeNode *pRoot)
{
if (pRoot == NULL)
return 0;
int leftHeight = TreeHeightR(pRoot->pLeft);
int rightHeight = TreeHeightR(pRoot->pRight);
int rootPath = leftHeight + rightHeight;
int leftPath = FarDistance(pRoot->pLeft);
int rightPath = FarDistance(pRoot->pRight);
return Max(rootPath, leftPath, rightPath);
}
//优化
int FarDistance2(BTreeNode *pRoot, int *pHeight)
{
if (pRoot == NULL)
{
*pHeight = 0;
return 0;
}
int leftHeight, rightHeight;
int leftPath = FarDistance2(pRoot->pLeft, &leftHeight);
int rightPath = FarDistance2(pRoot->pRight, &rightHeight);
int rootPath = leftHeight + rightHeight;
*pHeight = leftHeight > rightHeight ? (leftHeight + 1) : (rightHeight + 1);
return Max(rootPath, leftPath, rightPath);
}
有前序遍历和中序遍历重建二叉树
一般,前序遍历的第一个数字就是根节点,由根节点的值我们在中序遍历的序列中可以根据根节点的值区分出左子树还有右子树,以及每个子树的结点的数目,然后我们由此在前序遍历的序列中划分出相应的左右子树,进行递归进行。
BTreeNode *CreatTreeByPreAndIn(char preOrder[], int preSize, char inOrder[], int inSize)
{
if (preSize <= 0)
return NULL;
char root = preOrder[0];//在前序中找到根节点
int i = 0;
for (i = 0; i < inSize; i++)//在中序中找到根
{
if (inOrder[i] == preOrder[0])
{
break;
}
}
if (i == inSize)
{
assert(0);
}
BTreeNode *pRoot = CreateNode(root);
pRoot->pLeft = CreatTreeByPreAndIn(preOrder + 1, i, inOrder, i);
pRoot->pRight = CreatTreeByPreAndIn(preOrder + 1 + i, preSize - 1 - i, inOrder + i + 1, inSize - 1 - i);
return pRoot;
}
- 二叉树的镜像
从根结点开始,先交换根结点的左右孩子, 然后再依次交换根结点的左右孩子的孩子……
void Mirror(BTreeNode *pRoot)
{
BTreeNode *pLeft;
if (pRoot == NULL)
return NULL;
if (pRoot->pLeft == NULL&&pRoot->pRight == NULL)
return NULL;
pLeft = pRoot->pLeft;
pRoot->pLeft = pRoot->pRight;
pRoot->pRight = pLeft;
Mirror(pRoot->pLeft);
Mirror(pRoot->pRight);
}
- 求二叉树中两个结点的最近公共祖先结点
从根节点开始遍历,如果node1和node2中的任一个和root匹配,那么root就是最低公共祖先。 如果都不匹配,则分别递归左、右子树,如果有一个 节点出现在左子树,并且另一个节点出现在右子树,则root就是最低公共祖先. 如果两个节点都出现在左子树,则说明最低公共祖先在左子树中,否则在右子树。
BTreeNode *FindLCA(BTreeNode *pRoot, BTreeNode *n1, BTreeNode *n2)
{
BTreeNode *left;
BTreeNode *right;
if (pRoot == NULL)
return NULL;
if (n1 == pRoot || n2== pRoot)
return pRoot;
left = FindLCA(pRoot->pLeft, n1, n2);
right = FindLCA(pRoot->pRight, n1, n2);
if (left == NULL)
return right;
else if (right == NULL)
return left;
else
return pRoot;
}