二叉树基于递归模板的算法题目(王道算法题)

本文介绍了多种二叉树操作的递归算法,包括计算节点层次、先序遍历输出节点及层次、统计度为1、非叶子和度为0的节点个数、求树高度和宽度、删除叶节点、寻找最大值以及交换节点子节点。这些算法展示了二叉树的基本操作和遍历策略。
摘要由CSDN通过智能技术生成

() 1、计算指定结点*p所在的层次

#include <stdio.h>


/*
	思想:
		在先序遍历的基础上增加一个判断,判断两结点是否相等
	
	步骤:
		(1)if树为空,return 0;
		(2)if两结点相等,return 1;
		(3)递归地在左子树中查找,返回l 
		(4)递归地在右子树中查找,返回r 
		(5)如果在树中找到p(通过判断l和r,只要有一个返回1则证明找到),
			那么比较左子树返回的l和右子树返回的r,返回较大者+1 
*/

int getLevel(BiTree T,BSTNode *p){
	if(T==NULL)
		return 0;
	if(T->data==p->data)
		return 1;
	int l=getLevel(T->lchild);
	int r=getLevel(T->rchild);
	if(l||r){
		if(l>r)
			return l+1;
		else
			return r+1; 
	}
}

2、以先序序列输出一颗二叉树中所有结点的数据值及结点所在的层次

#include <stdio.h>

/*
	思想:
		在先序遍历的基础上,增加了深度的参数 
*/

void preOrder(BiTree T,int deep){
	if(T){
		printf("data:%s,deep:%d",T->data,deep);
		preOrder(T->lchild,deep+1);
		preOrder(T->rchild,deep+1);
	}
} 

3.1、统计二叉树中度为1的结点个数

#include <stdio.h>

/*
	思想: 
		度为1的结点即左子树和右子树只有一个非空!! 
*/

int preOrder(BiTree T){
	if(T==NULL)
		return 0;
	else if(T->lchild!=NULL&&T->rchild==NULL||T->rchild!=NULL&&T->lchild==NULL)
		return preOrder(T->lchild)+preOrder(T->rchild)+1;
	else
		return preOrder(T->lchild)+preOrder(T->rchild)
}

3.2 统计二叉树的非叶子结点

int preOrder(BiTree T){
	if(T==NULL)
		return 0;
	if(T->lchild==NULL&&T->rchild==NULL)
		return 0;
	return preOrder(T->lchild)+preOrder(T->rchild)+1;		
}

4、统计二叉树度为0的结点个数

#include <stdio.h>

int preOrder(BiTree T){
	if(T==NULL)
		return 0;
	else if(T->lchild==NULL&&T->rchild==NULL)
		return 1;
	else 
		return preOrder(T->lchild)+preOrder(T->rchild);
}

(2)要么定义一个全局变量n

int n=0;
void preOrder(BiTree T){
	if(T){
		if(T->lchild==NULL&&T->rchild==NULL)
			n++;
		preOrder(T->lchild);
		preOrder(T->rchild);
	}
}

5、假设二叉树采用二叉链表存储结构,设计一个算法求二叉树的高度

#include <stdio.h>

/*
*	递归嘛,考虑两个条件:递归体和递归出口
	步骤:
        (1)如果树为空,那么返回0;
		(2)如果树不为空,
            递归该结点的左子树    --- 递归体
            递归该结点的右子树    --- 递归体
            返回子树最大高度+1(加1是因为还有根结点) ---  递归出口
*/

int BtDepth(BiTree T){
	if(T==NULL)
		return 0;
	int ldep=BtDepth(T->lchild);
	int rdep=BtDepth(T->rchild);
	if(ldep>rdep)
		return ldep+1;
	else
		return rdep+1;
}

6、统计二叉树的宽度

(1)递归

#include <stdio.h> 

#define maxSize 5
/*
	思想:
		先求每一层宽度,并保存在数组a中;然后再比较数组a中的最大值即为宽度。 
		求每一层的宽度函数参数为(树,数组,深度)
			- 数组是用来存储同一层的结点数(也就是每一层的宽度),
			- 深度是用来代表递归的是哪一层(所以初始应该为1,从第一层开始)		 		 
*/

//求每一层的宽度 
void levelWidth(BiTree T,int *a,int deep){
	if(T){
		a[deep]++;
		levelWidth(T->lchild, a, deep+1);
		levelWidth(T->rchild, a, deep+1)
	}
} 
//求树的宽度
int width(BiTree T){
	int a[maxSize+1] , deep=1; //maxSize代表的就是树的深度(然后从1开始存储,所以需要加1) 
	for(int i = 0; i< maxSize+1; i++)
		a[i] = 0;
	levelWidth(T, a, deep);//求每一层的宽度并保存在数组a中
	int maxWidth = 0;//保存树的宽度 
	for(int i = 0; i < maxSize + 1; i++){
		if(maxWidth < a[i])
			maxWidth = a[i];
	} 
	return a[i];
} 

7、从二叉树删除所有叶结点

#include <stdio.h> 

/*
	思想:
		从上往下遍历,在先序遍历的基础上删除叶结点
	
	步骤: 
		(1)若树为空,返回
		(2)判断该节点的左孩子是否为叶结点,若是则将该结点的左孩子置空 
		(3)判断该节点的右孩子是否为叶结点,若是则将该结点的右孩子置空 
		(4)递归地删除左子树的叶结点
		(5)递归地删除左子树的叶结点 
*/

void Del(BiTree T){
	BiTree p=T;
	if(p==NULL){
		return;
	}else{
        if(p->lnode->lnode==NULL&&p->lnode->rnode==NULL){
		    free(p->lnode);
		    T->lnode=NULL; //父结点的左孩子指针置空
	    }
        if(p->rnode->lnode==NULL&&p->rnode->rnode==NULL){
		    free(p->rnode);
		    T->rnode=NULL; //父结点的右孩子指针置空
	    }  
    } 
	Del(T->lnode);
	Del(T->rnode);			
}

8、计算二叉树中各结点中的最大元素值

(1)定义一个全局变量记录最大值

int maxs=0;
void preOrder(BiTree T){
	if(T){
		if(T->ele>maxs)
			maxs=T->ele; 
		preOrder(T->lnode);
		preOrder(T->rnode);
	}
}

(2)没有定义全局变量

int preOrder(BiTree T){
	if(T){ 
		int max1=preOrder(T->lnode);
		int max2=preOrder(T->rnode);
		int max = max1 > max2? max1 : max2;
		return T->ele > max? T->ele : max;
	}
}

 9、交换二叉树中每个结点的两个子女

#include <stdio.h>
 
/*
	步骤: 
	(1)先把结点b的左孩子的左右子树进行交换,
	(2)再对结点b的右孩子的左右子树进行交换 
	(3)最后交换结点b的左右孩子
	当结点为空时递归结束!!
	
	思想: 
	乍一看是不是很眼熟,没错,其实就是递归版的后序遍历!!再后序遍历的基础上增加了交换结点而已。 
*/
 
void swap(BiTree T){
	if(T){
		swap(T->lchild);//递归地交换左子树 
		swap(T->rchild);//递归地交换右子树 
		//下面就是交换左右孩子 
		BiTree temp=T->lchild;
		T->lchild=T->rchild;
		T->rchild=temp;
	} 
} 

编辑不易,如果觉得有帮助可以点个赞支持一下呀

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值