问题描述:以二叉链表为存储结构,求二叉树的结点总数、叶子结点总数、度为2的结点数、高度、值为x的结点数、值为x的结点的深度、第k层的结点个数。
其实,学完二叉树的遍历后,结点的访问/计数都可以在递归遍历中加判断解决。
【求二叉树的结点总数】
直接利用递归求解:
//整颗树的节点个数 = 左子树节点个数 + 右子树节点个数 + 根节点个数1
int CountNodes(BiTree T)
{
if(T==NULL) return 0;
int n1 = CountNodes(T->lchild);
int n2 = CountNodes(T->rchild);
return n1+n2+1;
}
基于某种遍历思想的递归方法:
int CountNodes(BiTree T)
{
if(T==NULL) return 0;
return CountNodes(T->lchild) + CountNodes(T->rchild) + 1; //后序遍历
//return 1 + CountNodes(T->lchild) + CountNodes(T->rchild); //先序遍历
//return CountNodes(T->lchild) + 1 + CountNodes(T->rchild); //中序遍历
}
由于+1
的位置可以放在返回表达式的任何位置,对应着不同的遍历思想。
【求二叉树的叶子结点总数】
直接利用递归求解:
int CountLeaves(BiTree T)
{
if(!T) return 0;
if(!T->lchild&&!T->rchild) return 1;
return CountLeaves(T->lchild) + CountLeaves(T->rchild);
}
基于先序遍历的递归方法:
void CountLeaves(BiTree T, int &count)
{
if(T)
{
if(T->lchild==NULL&&T->rchild==NULL)
count++;
CountLeaves(T->lchild, count);
CountLeaves(T->rchild, count);
}
}
【求二叉树的高度】
//返回二叉树深度(层数)
int BiTreeDepth(BiTree T)
{
int LD, RD;
if(T==NULL)
return 0; //空树深度为0
else
{
LD = BiTreeDepth(T->lchild); //求左子树深度
RD = BiTreeDepth(T->rchild); //求右子树深度
return (LD>=RD?LD:RD) + 1;
}
}
【求二叉树度为2的结点数】
直接利用递归:
//统计二叉树中度为2的结点个数
int Degree2(BiTree T)
{
if(T==NULL)
return 0;
//若当前子树的根结点是2度结点,则子树的2度结点数等于该子树根结点的左子树2度结点数加上右子树2度结点数再加1
if((T->lchild!=NULL&&T->rchild!=NULL))
return Degree2(T->lchild)+Degree2(T->rchild)+1;
//若当前子树的根结点不是2度结点,则子树的2度结点数等于该子树根结点的左子树2度结点数加上右子树2度结点数
else
return Degree2(T->lchild)+Degree2(T->rchild);
}
//统计二叉树中度为0的结点个数
int Degree0(BiTree T)
{
if(T==NULL)
return 0;
//若当前子树的根结点是0度结点,则子树的0度结点数等于该子树根结点的左子树0度结点数加上右子树0度结点数再加1
if(T->lchild==NULL&&T->rchild==NULL)
return Degree0(T->lchild)+Degree0(T->rchild)+1;
//若当前子树的根结点不是0度结点,则子树的0度结点数等于该子树根结点的左子树0度结点数加上右子树0度结点数
else
return Degree0(T->lchild)+Degree0(T->rchild);
}
//统计二叉树中度为1的结点个数
int Degree1(BiTree T)
{
if(T==NULL)
return 0;
//若当前子树的根结点是1度结点,则子树的1度结点数等于该子树根结点的左子树1度结点数加上右子树1度结点数再加1
if((T->lchild==NULL&&T->rchild!=NULL)||(T->lchild!=NULL&&T->rchild==NULL))
return Degree1(T->lchild)+Degree1(T->rchild)+1;
//若当前子树的根结点不是1度结点,则子树的1度结点数等于该子树根结点的左子树1度结点数加上右子树1度结点数
else
return Degree1(T->lchild)+Degree1(T->rchild);
}
结点计数可以在遍历中解决。基于先序遍历的递归方法:
int n0, n1, n2; //全局变量
void Count(BiTree T)
{
if(T)
{
if(T->lchild&&T->rchild) n2++;
else if((T->lchild&&!T->rchild) || (!T->lchild&&T->rchild)) n1++;
else n0++;
Count(T->lchild);
Count(T->rchild)
}
}
【求二叉树中值为x的结点数】
int CountValue(BiTree T, TElemType x)
{
if(NULL == T)
return 0;
if(x == T->data)
return 1 + CountValue(T->lchild, x) + CountValue(T->rchild, x);
else
return CountValue(T->lchild, x) + CountValue(T->rchild, x);
}
//基于先序遍历
void CountValue(BiTree T, TElemType x, int &count)
{
if(T)
{
if(T->data==x) count++;
CountValue(T->lchild, x, count);
CountValue(T->rchild, x, count);
}
}
【求二叉树中值为x的结点的深度】
//调用该算法时,h置初值1,即Level(T,x,1)
int Level(BiTree T, TElemType x, int h)
{
if(T==NULL) //如果T为空树,返回0
return 0;
else if(T->data==x) //如果当前根结点的值为x,则返回h
return h;
else
{
int l = Level(T->lchild, x, h+1); //往左子树中查找(层次h需要增1)
if(l!=0)
return l; //在左子树中找到了,返回l
else //在左子树中未找到,再往右子树中查找(层次h需要增1)
return Level(T->rchild, x, h+1);
}
}
【求二叉树中第k层的结点个数】
//调用该算法 LevelNodes(T,1,k,0)
void LevelNodes(BiTree T, int h, int k, int &count)
{
if(T==NULL) //空树直接返回
return;
else //处理非空树
{
if(h==k) count++; //当前访问的结点在第k层时,count增1
else if(h<k) //若当前结点层次小于k,则递归处理左、右子树
{
LevelNodes(T->lchild, h+1, k, count);
LevelNodes(T->rchild, h+1, k, count);
}
}
}