1、求树的高度
思路:二叉树的高度等于左右子树里面的最大高度。
int high(BtNode* ptr)
{
if(ptr == NULL)return 0;
int L = high(ptr->lchild);
int R = high(ptr->rchild);
if(L>R) return (L+1);
return (R+1);
}
2、计算二叉树结点的总个数
思路:左结点个数+右结点个数
int Size(BtNode* ptr)
{
if(ptr ==NULL)
return 0;
else
{
return 1+Size(ptr->lchild)+Size(ptr->rchild);
}
}
扩展问题:求叶子结点个数,左单分支结点个数,右单分支结点个数,双分支结点个数
举个栗子: 求叶子结点个数
int SizeLeaf(BtNode *ptr)
{
if(ptr == NULL)
{
return 0;
}
else if(ptr->lchild ==NULL&&ptr->rchild ==NULL)//其他的子问题只需要把判断条件修改一下就行了,有左孩子或者有右孩子或者都有。
{
return 1;
}else
{
return SizeLeaf(ptr->lchild) + SizeLeaf(ptr->rchild);
}
}
3、二叉树的层序遍历
思路:
1、层序遍历用一个队列来实现。
2、让根节点A先从队尾入队,然后把根节点的左右孩子依次入栈,这样第二层BG就在队列里面的了。出队序列也就是第二层的层序遍历。
3、让队头元素B出队,然后B的左右结点入栈,再让队头元素G出队,然后G的左右结点入队。这样第三层就在队列里面对了。出队序列也就是第三层的层序遍历。
4、C出队,C的左右结点为空,D出队,EF入队,H出队,H的左右结点为空,队列为空,层序遍历结束。
void LevelOrder(BtNode *ptr)
{
deque<BtNode*> que;
que.push_front(ptr);
while(!que.empty())
{
BtNode *p = que.front();
que.pop_front();
printf("%c,",p->data);
if(p->lchild!=NULL)
{
que.push_front(p->lchild);
}
if(p->rchild!=NULL)
{
que.push_front(p->rchild);
}
}
}
层序遍历的扩展,打印一个树的第K层
思路:两种方式实现。
1、(用到了队列)可以再上面的层序遍历在循环的最后统计一下层数,然后到了题目需要的层数再打印。
2、(不用队列)先找到第K层,即从左右结点同时开始找,找到了,就打印。
主要实现一下第二种
步骤:
(1)、假设K是2,根节点为第0层。
(2)、首先是根节点不为空,然后就是根节点的左子树不为空,递归调用,传入K-1,以及根节点的左子树B
(3)、首先是B不为空,然后K!=0,此时K=1,继续访问B的左子树C,以及传入k-1
(4)、首先是C不为空,然后K==0,打印C,然后return,回到B,此时应该访问B的右子树了,K=1,然后进入右子树D;
(5)、打印D以后,return,然后B的下一层访问完了,接着就是往回退到A,该访问A的右子树了
(6)……
……
void Printf_KLevelData(BtNode* ptr,int k)
{
if(k<0 || ptr == NULL) return;
if(k==0 && ptr!=NULL)
{
printf("%c,",ptr->data);
return;
}
if(ptr->lchild!=NULL)
{
Printf_KLevelData(ptr->lchild,k-1);
}
if (ptr->rchild!=NULL)
{
Printf_KLevelData(ptr->rchild,k-1);
}
}
4、找两个节点的最近公共双亲
思路:
1、假设找E H 的最近公共双亲,从树形图里面看到最近的公共双亲是A
2、首先,从根节点出发,如果根节点等于传入的孩子结点或者根节点为空,返回空。
3、去根节点的左子树找,左子树不为空也不等于E H,继续往左找,C不为空也不等于E H,继续去C的左子树找,左子树为空,返回空,则C的左子树返回值是空,然后去C 的右子树找,为空,返回空,这时C结点的左右都返回的是空,则B的左子树返回值为空,没找到EH,去B的右子树找,不为空也不等于EH,去D的左子树找,找到E,返回E结点,去D的右子树找,F不等于EH,F的左右子树都返回空,则D的右子树返回空。只有D的左子树返回不为空,所以返回E结点,然后B的右子树返回E,接着,A的左子树返回空E
4、去A的右子树找,返回H,
5、所以A的左右子树分别返回E和H结点,最后最近公共双亲就返回的是A
BtNode* NearParent(BtNode *ptr,BtNode* child1,BtNode* child2)
{
if(ptr == NULL || ptr == child1 || ptr == child2)
{
return ptr;
}
BtNode* left = NearParent(ptr->lchild,child1,child2);
BtNode* right = NearParent(ptr->rchild,child1,child2);
if(left!=NULL && right!=NULL)
{
return ptr;
}
return left == NULL ? right:left;
}
BtNode* FindNearParent(BtNode *ptr,BtNode* child1,BtNode* child2)
{
if(ptr == NULL || child1 == NULL || child2 == NULL ||
child1 == ptr || child1 == ptr)
{
return NULL;
}
else
{
return NearParent(ptr,child1,child2);
}
}
5、求二叉树上两个结点的最大距离。
思路:首先明白,二叉树上的最远距离只有三种情况
(1)根节点左子树的最大距离
(2)根节点右子树的最大距离
(3)离根节点左孩子的最远距离+离根节点右孩子的最大距离+1(即横跨根节点)
这三者的最值就是这颗树的最大距离
具体代码:
FindMax(head,record)
{
if(NULL == head)
{
record[0] = 0;
return 0;
}
int lMax = FindMax(head->left,record);
int maxfromleft = record[0];
int rMax = FindMax(head->right,record);
int maxfromright = record[0];
int curNodeMax = maxfromleft + maxfromright +1;
record[0] = Max(maxfromleft ,maxfromright)+1;
return Max(Max(lMax ,rMax),curNodeMax );
}
int MaxDistance(BtNode *head,int[] record)
{
int record[1] = {0};
FindMax(head,record);
}
6,关于二叉树的判断
1> 比较两颗二叉树是否完全相等(结构,数值)。
bool Equal(BtNode* pa,BtNode* pb)
{
return (pa == NULL && pb == NULL) || (pa != NULL && pb != NULL && pa->data == pb->data && Equal(pa->lchild,pb->lchild)
&& Equal(pa->rchild,pb->rchild));
}
2>判断一颗二叉树是否是一颗平衡二叉树
平衡二叉树的定义 : 要么是一颗空树,要不是空树那这棵树的每个子树的左右子树高度差的绝对值不超过一;
bool res;
int GetHight(BtNode *ptr,int level)
{
if(ptr == NULL)return level;
int L = GetHight(ptr->lchild,level+1);
if(!res)
{
return level;
}
int R = GetHight(ptr->rchild,level+1);
if(!res)
{
return level;
}
if((L-R)>1 || (L-R)<-1)
{
res = false;
}
return L>R?L:R;
}
bool Is_Balance_BinaryTree(BtNode *ptr)
{
res = true;
GetHight(ptr,1);
return res;
}