文章目录提示:兰有秀兮菊有芳,怀佳人兮不能忘
- 题目
- 递归(回溯)
- 递归(不回溯)
- 迭代
- 运行截图
- 总结
题目
给你一个二叉树的根节点 root ,按任意顺序 ,返回所有从根节点到叶子节点的路径
输入:root = [1,2,3,null,5]
输出:[“1->2->5”,“1->3”]
思路:简单来说就是定义一个result 用来存放结果 一个path 用来存放路径 但是很多人被搞蒙的是需不需要回溯,若是在本次中的path改变了 就需回溯,因为下一个路径的路不能是上一个走过的路,若是没有改变path的值他们走的路自己不同
递归(回溯)#include
#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();//处理完数据之后需要d出 来取此结点右子树的值
//上面的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 PreOrder(BiNTree* T,vector<string> &result,string &path){
if(T->Lchild==NULL&&T->Rchild==NULL){//遇到叶子结点一路返回
path+=to_string(T->data);
result.push_back(path);
return;
}
//此时不是叶子节点 我们就需要深入 找到叶子结点
if(T->Lchild){
string temp=path;
path=path+to_string(T->data)+"->";
PreOrder(T->Lchild,result,path);
path=temp;//回溯
}
if(T->Rchild){
string temp=path;
path=path+to_string(T->data)+"->";
PreOrder(T->Rchild,result,path);
path=temp;//回溯
}
}
string Deal(BiNTree* T){
if(T==NULL) return " ";
string path;
vector<string> result;
PreOrder(T,result,path);
cout<<"此时的路径是"<<endl;
for(int i=0;i<result.size();i++){
cout<<result[i]<<endl;
}
}
main(){
BiNTree* T=NULL;
Creat(T);
Deal(T);
}
递归(不回溯)
#include
#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();//处理完数据之后需要d出 来取此结点右子树的值
//上面的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 PreOrder(BiNTree* T,vector<string> &result,string path){
if(T->Lchild==NULL&&T->Rchild==NULL){//遇到叶子结点一路返回
path+=to_string(T->data);
result.push_back(path);
return;
}
//此时不是叶子节点 我们就需要深入 找到叶子结点
if(T->Lchild){
PreOrder(T->Lchild,result,path+to_string(T->data)+"->");
}
if(T->Rchild){
PreOrder(T->Rchild,result,path+to_string(T->data)+"->");
}
}
string Deal(BiNTree* T){
if(T==NULL) return " ";
string path;
vector<string> result;
PreOrder(T,result,path);
cout<<"此时的路径是"<<endl;
for(int i=0;i<result.size();i++){
cout<<result[i]<<endl;
}
}
main(){
BiNTree* T=NULL;
Creat(T);
Deal(T);
}
迭代
记住一句关键 就是每一个结对对应一个字符串所以你要使用的结构是栈其中的元素是string 主要就是同步 对结点进行什么 *** 作 相应的对结点对印的路径进行什么 *** 作,记住此结点路径是在上一个结点路径的结果上进行加长的
你就可以写出代码 解析放在代码中了
#include
#define ElemType int
using namespace std;
typedef struct BiNTree{
struct BiNTree* Lchild;
ElemType data;
struct BiNTree* Rchild;
}BiNTree;
/*层序的思想是,首先需要判断此时第一个元素是否为空 为此
若是为空就不用需要进入树队中了 若是第一个元素不为空 则进入队列中
然后为其分配左右子树,若是值为-1 则表示此时的孩子为空 不需要入队
若是值不为-1 ,让其作为此时结点的孩子,然后此孩子入队
直到元素值队列为空*/
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();//处理完数据之后需要d出 来取此结点右子树的值
//上面的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 PreOrder(BiNTree* T,vector<string> &result){
stack<BiNTree*> S;
stack<string> path;
if(T==NULL) return;
S.push(T);
path.push(to_string(T->data));//因为本来是整形 这里要转换成字符串型 使用to_string()便可
while(!S.empty()){
cout<<"进入while";
BiNTree* cur=S.top();//取出当前栈顶元素
cout<<"此时栈顶元素是"<<cur->data<<endl;
S.pop();
string str1=path.top();//取出当前栈顶元素对应的字符串
cout<<"此时栈顶元素对应的字符串是"<<str1<<endl;
path.pop();
if(cur->Lchild==NULL&&cur->Rchild==NULL){
//说明此时的路径 可以放在结果集中
cout<<"找到此时的叶子结点"<<cur->data<<endl;
result.push_back(str1);
}
else{//如果不是叶子结点 则将此结点的的左右孩子放入栈集中
if(cur->Rchild){
S.push(cur->Rchild);
path.push(str1+"->"+to_string(cur->Rchild->data));
cout<<"将右结点"<<cur->Rchild->data<<"放入栈中"<<endl;
}
if(cur->Lchild){
S.push(cur->Lchild);//记住右左顺序
path.push(str1+"->"+to_string(cur->Lchild->data));
cout<<"将左结点"<<cur->Lchild->data<<"放入栈中"<<endl;
}
//同时制造两个字符串放入路径栈中
}
}
}
void Deal(BiNTree* T){
vector<string> result;//用来存放结果集 这里存放的元素也是string
PreOrder(T,result);
//此时遍历二维向量
cout<<"最后发现的路径是"<<endl;
for(int i=0;i<result.size();i++){
cout<<result[i]<<endl;
}
}
main(){
BiNTree* T=NULL;
Creat(T);
Deal(T);
}
运行截图
总结
若是感觉文章对你有用的话 不要mean一个赞 你的点赞是作者奋斗的的动力
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)