左叶子之和

知我者,谓我心忧;不知我者,谓我何求

题目

给定二叉树的根节点 root ,返回所有左叶子之和。
请添加图片描述
输入: root = [3,9,20,null,null,15,7]
输出: 24
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24

思路

其实就是遍历一个树 设置一个变量 若是左叶子累加即可 左叶子的特点是什么 是上一个结点的左孩子,并且这个结点没有左右子树,所以是不是可以想到使用双指针的方式
接下来写出代码

双指针

一遍过 不要问怎么做到一遍过的, 问就是天赋

#include<bits/stdc++.h>
#define ElemType int
using namespace std;
typedef struct BiNTree{
	struct BiNTree* Lchild;
	ElemType data;
	struct BiNTree* Rchild;
}BiNTree;
/*层序的思想是,首先需要判断此时第一个元素是否为空 为此 
若是为空就不用需要进入树队中了  若是第一个元素不为空 则进入队列中
然后为其分配左右子树,若是值为-1 则表示此时的孩子为空  不需要入队
若是值不为-1 ,让其作为此时结点的孩子,然后此孩子入队 
直到元素值队列为空*/ 
vector<string> result;
void Creat(BiNTree* &T){
	int val;
	BiNTree* cur;//定义一个cur 
	queue<ElemType> Q;
	queue<BiNTree*> TreeQue;
	cout<<"请输入层序遍历的序列"<<endl;
	while(scanf("%d",&val)!=EOF) Q.push(val);
	if(Q.front()==-1){
		cout<<"树为空"<<endl; 
		T=NULL;
		return ;
	} 
	else{ 
		T=(BiNTree*)malloc(sizeof(BiNTree));
		T->data=Q.front(); 
		TreeQue.push(T);
	}
	Q.pop();
	while(!Q.empty()){//我们每一次处理 处理的都是左右孩子,所以也就需要两个if
		cur=TreeQue.front();//取出此时树队中的第一元素
		if(Q.front()==-1){//此时这个结点值为NULL  
			cout<<cur->data<<"左孩子为空"<<endl;
			cur->Lchild=NULL; 
		}
		else{//新生成一个树结点用来存放此时的结点信息 
			cout<<cur->data<<"左孩子为"<<Q.front()<<endl; 
			cur->Lchild=(BiNTree*)malloc(sizeof(BiNTree)) ;
			cur->Lchild->data=Q.front();
			TreeQue.push(cur->Lchild);
		}
		Q.pop();//处理完数据之后需要弹出 来取此结点右子树的值 
		//上面的if  else 是处理结点左孩子  下面我们来处理右孩子 
		if(Q.front()==-1){
			cout<<cur->data<<"右孩子为空"<<endl;;
			cur->Rchild=NULL;
		} 
		else{
			cout<<cur->data<<"右孩子为"<<Q.front()<<endl; 
			cur->Rchild=(BiNTree*)malloc(sizeof(BiNTree));
			cur->Rchild->data=Q.front();
			TreeQue.push(cur->Rchild); 
		}
		Q.pop();
		TreeQue.pop();
	}
} 

//使用双指针要特别注意根节点 要拿出来讨论 
void Deal(BiNTree* T,BiNTree* pre,int &sum){
	if(T->Lchild==NULL&&T->Rchild==NULL){
		if(pre->Lchild==T){
			sum+=T->data;
		}
		return;		
	}
	if(T->Lchild){
		Deal(T->Lchild,T,sum);
	} 
	if(T->Rchild){
		Deal(T->Rchild,T,sum);
	}
}
main(){
	BiNTree* T=NULL;int sum=0;
	Creat(T); 
	Deal(T,T,sum);	
	cout<<"此时的左叶子是"<<sum;
}

单指针

不会双指针怎么办,我们就使用最简单的递归 这里使用什么遍历方式呢?这里认为使用后序,这样左子树加右子树 不是美滋滋,但是若是没有左子树 或者右子树 又该怎么办?这就是递归到什么时候return的问题 之前我们有到叶子结点停 也有到NULL停 还有一个问题就是 怎么看与父节点的关系 若是到达叶子结点 返回一个0 作为标志 给上一层 若是上一层接受到的就是零 有时此时结点的左孩子 也就可以加 使用这里认为依然是叶子 返回 简单一句话 通过返回值来判断与父节点之间的关系

#include<bits/stdc++.h>
#define ElemType int
using namespace std;
typedef struct BiNTree{
	struct BiNTree* Lchild;
	ElemType data;
	struct BiNTree* Rchild;
}BiNTree;
/*层序的思想是,首先需要判断此时第一个元素是否为空 为此 
若是为空就不用需要进入树队中了  若是第一个元素不为空 则进入队列中
然后为其分配左右子树,若是值为-1 则表示此时的孩子为空  不需要入队
若是值不为-1 ,让其作为此时结点的孩子,然后此孩子入队 
直到元素值队列为空*/ 
vector<string> result;
void Creat(BiNTree* &T){
	int val;
	BiNTree* cur;//定义一个cur 
	queue<ElemType> Q;
	queue<BiNTree*> TreeQue;
	cout<<"请输入层序遍历的序列"<<endl;
	while(scanf("%d",&val)!=EOF) Q.push(val);
	if(Q.front()==-1){
		cout<<"树为空"<<endl; 
		T=NULL;
		return ;
	} 
	else{ 
		T=(BiNTree*)malloc(sizeof(BiNTree));
		T->data=Q.front(); 
		TreeQue.push(T);
	}
	Q.pop();
	while(!Q.empty()){//我们每一次处理 处理的都是左右孩子,所以也就需要两个if
		cur=TreeQue.front();//取出此时树队中的第一元素
		if(Q.front()==-1){//此时这个结点值为NULL  
			cout<<cur->data<<"左孩子为空"<<endl;
			cur->Lchild=NULL; 
		}
		else{//新生成一个树结点用来存放此时的结点信息 
			cout<<cur->data<<"左孩子为"<<Q.front()<<endl; 
			cur->Lchild=(BiNTree*)malloc(sizeof(BiNTree)) ;
			cur->Lchild->data=Q.front();
			TreeQue.push(cur->Lchild);
		}
		Q.pop();//处理完数据之后需要弹出 来取此结点右子树的值 
		//上面的if  else 是处理结点左孩子  下面我们来处理右孩子 
		if(Q.front()==-1){
			cout<<cur->data<<"右孩子为空"<<endl;;
			cur->Rchild=NULL;
		} 
		else{
			cout<<cur->data<<"右孩子为"<<Q.front()<<endl; 
			cur->Rchild=(BiNTree*)malloc(sizeof(BiNTree));
			cur->Rchild->data=Q.front();
			TreeQue.push(cur->Rchild); 
		}
		Q.pop();
		TreeQue.pop();
	}
} 

//使用双指针要特别注意根节点 要拿出来讨论 
int PostOrder(BiNTree* T,int &sum){
	if(T->Lchild==NULL&&T->Rchild==NULL){
		return 0;//此时的零作为一种达到叶子的标志	
	}
	if(T->Lchild){
		if(PostOrder(T->Lchild,sum)==0){
			//说明T的左孩子就是等于叶子结点
			sum+=T->Lchild->data; 
		}
	} 
	if(T->Rchild){
		//右孩子返回的是不是0都无所谓 因为下一个结点只可能是此结点的右孩子 
		PostOrder(T->Rchild,sum);
	}
}
main(){
	BiNTree* T=NULL;int sum=0;
	Creat(T); 
	PostOrder(T,sum);	
	cout<<"此时的左叶子是"<<sum;
}

迭代

这里也提供一个迭代版本吧 迭代版本最好理解这题 遍历每一个结点 若是满足左叶子的定义 直接累加即可 在这里写一种 其他都一样的条件累加即可

#include<bits/stdc++.h>
#define ElemType int
using namespace std;
typedef struct BiNTree{
	struct BiNTree* Lchild;
	ElemType data;
	struct BiNTree* Rchild;
}BiNTree;
/*层序的思想是,首先需要判断此时第一个元素是否为空 为此 
若是为空就不用需要进入树队中了  若是第一个元素不为空 则进入队列中
然后为其分配左右子树,若是值为-1 则表示此时的孩子为空  不需要入队
若是值不为-1 ,让其作为此时结点的孩子,然后此孩子入队 
直到元素值队列为空*/ 
vector<string> result;
void Creat(BiNTree* &T){
	int val;
	BiNTree* cur;//定义一个cur 
	queue<ElemType> Q;
	queue<BiNTree*> TreeQue;
	cout<<"请输入层序遍历的序列"<<endl;
	while(scanf("%d",&val)!=EOF) Q.push(val);
	if(Q.front()==-1){
		cout<<"树为空"<<endl; 
		T=NULL;
		return ;
	} 
	else{ 
		T=(BiNTree*)malloc(sizeof(BiNTree));
		T->data=Q.front(); 
		TreeQue.push(T);
	}
	Q.pop();
	while(!Q.empty()){//我们每一次处理 处理的都是左右孩子,所以也就需要两个if
		cur=TreeQue.front();//取出此时树队中的第一元素
		if(Q.front()==-1){//此时这个结点值为NULL  
			cout<<cur->data<<"左孩子为空"<<endl;
			cur->Lchild=NULL; 
		}
		else{//新生成一个树结点用来存放此时的结点信息 
			cout<<cur->data<<"左孩子为"<<Q.front()<<endl; 
			cur->Lchild=(BiNTree*)malloc(sizeof(BiNTree)) ;
			cur->Lchild->data=Q.front();
			TreeQue.push(cur->Lchild);
		}
		Q.pop();//处理完数据之后需要弹出 来取此结点右子树的值 
		//上面的if  else 是处理结点左孩子  下面我们来处理右孩子 
		if(Q.front()==-1){
			cout<<cur->data<<"右孩子为空"<<endl;;
			cur->Rchild=NULL;
		} 
		else{
			cout<<cur->data<<"右孩子为"<<Q.front()<<endl; 
			cur->Rchild=(BiNTree*)malloc(sizeof(BiNTree));
			cur->Rchild->data=Q.front();
			TreeQue.push(cur->Rchild); 
		}
		Q.pop();
		TreeQue.pop();
	}
} 
int LevelOrder(BiNTree* T){//这里我们是使用的是队列来完成这个操作
	queue<BiNTree*> Q; BiNTree* cur;int sum;
	if(T==NULL){//跟前面一样  若是为空则不需要进队  直接返回即可 
		return 0;; 
	}
	Q.push(T); 
	while(!Q.empty()){
		int size=Q.size();//需要一个值来保存 因为Q.size 是一直变得 
		for(int i=0;i<size;i++){
			cur=Q.front();
			if(cur->Lchild&&cur->Lchild->Lchild==NULL&&cur->Lchild->Rchild==NULL){//当前结点有左孩子 左左孩子是叶子结点 
				cout<<"找到此时左结点"<<cur->Lchild->data<<endl;
				sum+=cur->Lchild->data;
			}
			if(cur->Lchild) Q.push(cur->Lchild);
			if(cur->Rchild) Q.push(cur->Rchild); 
			Q.pop();
		}
	}
	return sum;
} 
main(){
	BiNTree* T=NULL;int sum=0;
	Creat(T); 	
	cout<<"此时的左叶子之和是"<<LevelOrder(T);
}

运行结果

请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值