二叉树的结点类型如下:
typedef struct BtNode
{
BtNode *leftchild;
BtNode *rightchild;
ElemType data;
}BtNode, *BinaryTree;
1. 给你一颗普通的二叉树,求二叉树中最远的两个节点的距离
分析:
1、如果具有最远距离的两个结点之间的路径经过根结点,则最远距离就是这个根节点左边的深度加上根节点的右边的深度。
2、如果具有最远距离的两个结点之间的路径不经过根节点,则最远距离的结点就在根节点的某一棵子树上的两个叶子结点。
使用distance记录这个最远的距离。后序遍历二叉树中每一个结点,对于每一个结点先算出左边和右边的深度和然后与distance里面的数据进行比较,如果结果大于distance则更新distance的值。
int _GetFarDistance(BtNode* root,int &distance)
{
if(root==NULL) return 0;
int Left=_GetFarDistance(root->_left,distance);
int Right=_GetFarDistance(root->_right,distance);
if((Left+Right)>distance)
{
distance=Left+Right;
}
return Left>Right?Left+1:Right+1;
}
int GetFartherDistance(BtNode* root)
{
assert(root);
int distance=0;
_GetFarDistance(root,distance);
return distance;
}
2. 由前序遍历和中序遍历重建二叉树(前序序列:1 2 3 4 5 6 - 中序序列:3 2 4 1 6 5)
前序遍历的每一结点,都是当前子树的根节点,我们可以根据前序遍历的序列对中序遍历的序列进行划分。
int IsIndex(ElemType *is,ElemType x,int n)
{
for (int i = 0;i<n;++i)
{
if (is[i] == x)
{
return i;
}
}
return -1;
}
BtNode * CreatePI(ElemType *ps,ElemType *is,int n)
{
BtNode *s = NULL;
if (n > 0)
{
s = BuyNode();
s->data = ps[0];
int pos = IsIndex(is,ps[0],n);
if (pos == -1)
{
exit(1);
}
s->leftChild = CreatePI(ps+1,is,pos);
s->rightChild = CreatePI(ps+pos+1,is+pos+1,n-pos-1);
}
return s;
}
BtNode * CreateTreePI(ElemType *ps,ElemType *is,int n)
{
if (ps == NULL || is == NULL || n < 1)
{
return NULL;
}
else
{
return CreatePI(ps,is,n);
}
}
3. 判断一棵树是否是完全二叉树
我们可以根据完全二叉树的定义,按照层序遍历一颗树,当遇到空结点时如果这棵树已经遍历完毕,则这棵树就是完全二叉树,如果遇到空结点的后面还有元素则这棵树就不是完全二叉树。
bool IsCompleteBinaryTree(BTNode* root) //判断一颗二叉树是否是完全二叉树
{
if (root == NULL)
return false;
queue<BTNode*> q;
int flag = 0;
q.push(root);
while (!q.empty())
{
BTNode<int>* cur = q.front();
q.pop();
if (cur->_left)
{
if (flag)
return false;
q.push(cur->_left);
}
else
{
if (flag == 0)
flag = 1;
}
if (cur->_right)
{
if (flag)
return false;
q.push(cur->_right);
}
else
{
if (flag == 0)
flag = 1;
}
}
方法2:
什么是完全二叉树呢???
如果一颗二叉树的只有最后两层结点的度能小于2,其余结点的度都等于2。且最后一层的结点从最左边依次排列。
思路: 若父节点不空,我们将二叉树左右孩子依次放入队列(空结点也放入队列),依次出队,遇到第一个空结点,我们判断后续队列中的节点是否为空,若空,则是完全二叉树。
bool Is_Comp_BinaryTree(BtNode *ptr)
{
if (ptr == NULL) return true;
queue<BtNode *> qu;
qu.push(ptr);
while (!qu.empty())
{
BtNode *p = qu.front(); qu.pop();
if (p == NULL)
{
break;
}
qu.push(p->leftchild);
qu.push(p->rightchild);
}
while (!qu.empty())
{
BtNode *p = qu.front(); qu.pop();
if (p != NULL) return false;
}
return true;
}
4. 后序和中序序列创建二叉树
int IsIndex(ElemType *is,ElemType x,int n)
{
for (int i = 0;i<n;++i)
{
if (is[i] == x)
{
return i;
}
}
return -1;
}
BtNode * CreateIL(ElemType *is,ElemType *ls,int n)
{
BtNode *s = NULL;
if (n > 0)
{
int pos = IsIndex(is,ls[n-1],n);
if (pos == -1)
{
exit(1);
}
s = BuyNode();
s->data = ls[n-1];
s->leftChild = CreateIL(is,ls,pos);
s->rightChild = CreateIL(is+pos+1,ls+pos,n-pos-1);
}
return s;
}
BtNode * CreateTreeIL(ElemType *is,ElemType *ls,int n)
{
if (is == NULL || ls == NULL || n < 1)
{
return NULL;
}
else
{
return CreateIL(is,ls,n);
}
}
5. 求两个节点的最近公共祖先
分析:
求两个结点的最近公共祖先有两种情况。
1、如果这两个结点不在一条线上,则它们就分别在最近的公共祖父的左右子树上。
2、如果这两个结点在一条线上,则它们之中深度最前的就是他们的最近的公共祖先。
思路:
给定一棵二叉树的头节点root,以及这棵二叉树的两个节点node1和node2,请返回node1和node2的最近公共祖先节点。我们可以后序遍历这棵树,用left记录左子树返回的结果,用right记录右子树返回的结果。
虽然是三种情况,但是不论是哪一种,只要返回left和right中不为空的就可以了
BTNode* _GetAncestor(BTNode root,BTNode node1,BTNode node2)
{
if (root == NULL)
return NULL;
BTNode left = _GetAncestor(root->_left, node1, node2);
BTNode right = _GetAncestor(root->_right, node1, node2);
if (left&&right)
return root;
if (root == node1)
return node1;
if (root == node2)
return node2;
if (left == NULL&&right)
return right;
if (right == NULL&&left)
return left;
return NULL;
}
BTNode* GetAncestor(BTNode* root, BTNode* node1, BTNode* node2)
{
assert(root);
assert(node1);
assert(node2);
BTNode* parent = NULL;
BTNode* left = NULL;
BTNode* right = NULL;
parent = _GetAncestor(root, node1, node2);
return parent;
}