第6章 二叉树其他的一些算法(重点:理解递归)

问题描述:以二叉链表为存储结构,求二叉树的结点总数、叶子结点总数、度为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);
		}
	}
}
发布了674 篇原创文章 · 获赞 103 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/qq_42815188/article/details/103787759