北邮22信通:二叉树显示路径的两种方法 递归函数保存现场返回现场的实例
北邮22信通一枚~
跟随课程进度每周更新数据结构与算法的代码和文章
持续关注作者 解锁更多邮苑信通专属代码~
获取更多文章 请访问专栏~
北邮22信通_青山如墨雨如画的博客-CSDN博客
一.讲解
要想实现二叉树的路径显示,我们要按照先后顺序做这样几件事:
1.判断是否能够找到路径;
2.如果能找到路径,则将路径存储起来,如果不能找到路径,则返回查询失败的信息;
3.将路径按照一定的方法打印出来;
1.递归详解:是否能够找到路径并将找到的可行路径存储起来的实现函数
template<class temp>
bool bintree<temp>::stl_search_path(temp target, binnode<temp>*& r, stack <binnode<temp>>& stk)
{if (r == NULL)return false;stk.push(*r);if (r->data == target)return true;else if (stl_search_path(target, r->leftchild, stk))return true;else if (stl_search_path(target, r->rightchild, stk))return true;stk.pop();return false;
}
首先我们向这个函数中传入3个参数,分别是待查找的目标,二叉树的根节点,一个空栈(用来存储路径);实现的具体过程运用了递归思想:对整个查找过程中的某次查找如果父节点数据域就是要查找的目标,返回真值;如果沿着他的左孩子找下去能找到目标,返回真值,如果沿着他的右孩子找下去能找到目标,返回真值。如果父节点不是目标并且沿着左孩子右孩子都找不到目标的话,弹出父节点返回假值。
这里用例子重新讲解递归函数保存现场返回现场的运行过程:

如上图,我们要查找到结点6的路径:
按照函数编写顺序:
1首先入栈,判断1不是6(函数第5、6行),继续执行;
template<class temp>
bool bintree<temp>::stl_search_path(temp target, binnode<temp>*& r, stack <binnode<temp>>& stk)
{if (r == NULL)return false;stk.push(*r);if (r->data == target)//现在是1,不是9return true;//执行完毕,继续向下执行;
}
执行到第7行,需要判断沿着1的左孩子2能不能找到合适路径,保存现场;
template<class temp>
bool bintree<temp>::stl_search_path(temp target, binnode<temp>*& r, stack <binnode<temp>>& stk)
{if (r == NULL)return false;stk.push(*r);if (r->data == target)return true;else if (stl_search_path(target, r->leftchild, stk))return true;/*执行到这一步,需要重新判断stl_search_path(target, r->leftchild, stk)是否为真值;函数保存现场不继续向下执行,将r->leftchild==2作为参数替代r==1,重新开始执行函数;*/
}
重新从第一行开始执行函数,2入栈,2不是6,向下执行;
template<class temp>
bool bintree<temp>::stl_search_path(temp target, binnode<temp>*& r, stack <binnode<temp>>& stk)
{if (r == NULL)return false;stk.push(*r);if (r->data == target)return true;//r==2不是9,继续向下执行;
}
执行到第7行,需要判断沿着2的左孩子4能不能找到合适路径,保存现场;
template<class temp>
bool bintree<temp>::stl_search_path(temp target, binnode<temp>*& r, stack <binnode<temp>>& stk)
{if (r == NULL)return false;stk.push(*r);if (r->data == target)return true;else if (stl_search_path(target, r->leftchild, stk))return true;/*执行到这一步,需要重新判断stl_search_path(target, r->leftchild, stk)是否为真值;函数保存现场不继续向下执行,将r->leftchild->leftchild==4作为参数替代r->leftchild==2,重新开始执行函数;*/
}
重新从第一行开始执行函数,4入栈,4不是6,向下执行;
template<class temp>
bool bintree<temp>::stl_search_path(temp target, binnode<temp>*& r, stack <binnode<temp>>& stk)
{if (r == NULL)return false;stk.push(*r);if (r->data == target)return true;else if (stl_search_path(target, r->leftchild, stk))return true;/*执行到这一步,需要重新判断stl_search_path(target, r->leftchild, stk)是否为真值;函数保存现场不继续向下执行,将r->leftchild->leftchild->leftchild==NULL作为参数替代r->leftchild->leftchild==4,重新开始执行函数;*/
}
发现4的左孩子是空,返回假值;
返回上一级现场,执行函数第8、9行,需要判断沿着4的右孩子能不能找到合适路径,保存现场;
template<class temp>
bool bintree<temp>::stl_search_path(temp target, binnode<temp>*& r, stack <binnode<temp>>& stk)
{if (r == NULL)return false;stk.push(*r);if (r->data == target)return true;else if (stl_search_path(target, r->leftchild, stk))return true;else if (stl_search_path(target, r->rightchild, stk))return true;/*执行到这一步,需要重新判断stl_search_path(target, r->leftchild, stk)是否为真值;函数保存现场不继续向下执行,将r->leftchild->leftchild->rightchild==NULL作为参数替代r->leftchild->leftchild==4,重新开始执行函数;*/
}
右孩子为空;
返回上一级现场,判断沿着2的右孩子5能不能找到可行的路径,保存现场,以此类推……
示意图如下:

2.打印路径的函数
template<class temp>
void bintree<temp>::stl_node_root_path(temp target)
{stack<binnode<temp>>stk;stl_search_path(target, this->root, stk);if (stk.empty())cout << target << "未能找到目标" << endl;else{cout << target << "结点到根节点的路径为:" << endl;binnode<temp>out;while (!stk.empty()){out = stk.top();if (stk.size() == 1)cout << out.data;elsecout << out.data << "->";stk.pop();}cout << endl;}
}
对于给定的二叉树,首先调用上面讲解过的函数,如果有可行路径就将可行路径通过函数存储到本函数的栈空间中,然后通过控制条件输出,最终可以实现打印的效果。
3.另一种存储方式
使用模板类定义的栈存储也未尝不可。
代码如下:
template<class temp>
void bintree<temp>::linkstack_node_root_path(temp target)
{linkstack<binnode<temp>>stk;linkstack_search_path(target, this->root, stk);if (stk.empty())cout << target << "未能找到目标" << endl;else{cout << target << "结点到根节点的路径为:" << endl;binnode<temp>out;while (!stk.empty()){out = stk.gettop();if (stk.getsize() == 1)cout << out.data;elsecout << out.data << "->";stk.pop();}cout << endl;}
}
template<class temp>
bool bintree<temp>::linkstack_search_path(temp target, binnode<temp>*& r, linkstack<binnode<temp>>& stk)
{if (r == NULL)return false;stk.push(*r);if (r->data == target)return true;else if (linkstack_search_path(target, r->leftchild, stk))return true;else if (linkstack_search_path(target, r->rightchild, stk))return true;stk.pop();return false;
}
二.完整代码:
2.1使用STL栈实现:
#include<iostream>
#include<stack>
using namespace std;class student
{
private:int ID;string name;
public:int existence;student(){this->ID = 0;this->name = "unknown name";this->existence = 0;}student(int ID, string name){this->ID = ID;this->name = name;this->existence = 1;}bool operator == (student& s){return ((this->ID == s.ID) && (this->name == s.name)) ? true : false;}friend ostream& operator<<(ostream& output, student& s){output << "\"" << s.ID << " " << s.name << "\"";return output;}
};template<class temp>
struct binnode
{temp data;binnode* leftchild;binnode* rightchild;
};template<class temp>
class bintree
{
private:void create(binnode<temp>*& r, temp data[], int i, int n);void release(binnode<temp>* r);
public:binnode<temp>* root;bintree(temp data[], int n);void stl_node_root_path(temp target);bool stl_search_path(temp target, binnode<temp>*& r, stack <binnode<temp>>& stk);~bintree();
};template<class temp>
void bintree<temp>::create(binnode<temp>*& r, temp data[], int i, int n)
{if (i <= n && data[i - 1].existence != 0){r = new binnode<temp>;r->data = data[i - 1];r->leftchild = NULL;r->rightchild = NULL;create(r->leftchild, data, 2 * i, n);create(r->rightchild, data, 2 * i + 1, n);}
}template<class temp>
bintree<temp>::bintree(temp data[], int n)
{create(this->root, data, 1, n);
}template<class temp>
void bintree<temp>::release(binnode<temp>* r)
{if (r != NULL){release(r->leftchild);release(r->rightchild);delete r;}
}template<class temp>
bintree<temp>::~bintree()
{release(this->root);
}template<class temp>
void bintree<temp>::stl_node_root_path(temp target)
{stack<binnode<temp>>stk;stl_search_path(target, this->root, stk);if (stk.empty())cout << target << "未能找到目标" << endl;else{cout << target << "结点到根节点的路径为:" << endl;binnode<temp>out;while (!stk.empty()){out = stk.top();if (stk.size() == 1)cout << out.data;elsecout << out.data << "->";stk.pop();}cout << endl;}
}template<class temp>
bool bintree<temp>::stl_search_path(temp target, binnode<temp>*& r, stack <binnode<temp>>& stk)
{if (r == NULL)return false;stk.push(*r);if (r->data == target)return true;else if (stl_search_path(target, r->leftchild, stk))return true;else if (stl_search_path(target, r->rightchild, stk))return true;stk.pop();return false;
}int main()
{system("color 0A");student stu[5] = { {1,"zhang"},{2,"wang"},{3,"li"},{4,"zhao"},{5,"liu"} };bintree<student>tree(stu, 5);student stu1(1, "zhang"), stu2(5, "liu"), stu3(6, "cao");tree.stl_node_root_path(stu1);tree.stl_node_root_path(stu2);tree.stl_node_root_path(stu3);return 0;
}
2.2使用模板类定义的栈实现:
#include<iostream>
using namespace std;class student
{
private:int ID;string name;
public:int existence;student(){this->ID = 0;this->name = "unknown name";this->existence = 0;}student(int ID, string name){this->ID = ID;this->name = name;this->existence = 1;}bool operator == (student& s){return ((this->ID == s.ID) && (this->name == s.name)) ? true : false;}friend ostream& operator<<(ostream& output, student& s){output << "\"" << s.ID << " " << s.name << "\"";return output;}
};
//二叉树声明部分
template<class temp>
struct binnode;
//栈
template <class temp>
struct node
{temp data;node<temp>* next;
};template <class temp>
class linkstack
{
public:binnode<temp>* r;int tag;linkstack() { top = NULL; }~linkstack();void push(temp x);temp pop();temp gettop();int getsize();bool empty(){return top == NULL ? true : false;}
private:node<temp>* top;
};template <class temp>
void linkstack<temp>::push(temp x)
{node<temp>* p = new node<temp>;p->data = x;p->next = this->top;this->top = p;
}template<class temp>
temp linkstack<temp>::pop()
{if (empty())throw "下溢";temp x = this->top->data;node<temp>* p = this->top;this->top = this->top->next;delete p;return x;
}template<class temp>
linkstack<temp>::~linkstack()
{while (this->top != NULL){node<temp>* p = this->top;this->top = this->top->next;delete p;}
}template<class temp>
temp linkstack<temp>::gettop()
{if (empty())throw"下溢";return this->top->data;
}template<class temp>
int linkstack<temp>::getsize()
{int num = 0;node<temp>* p = this->top;while (p != NULL){num++;p = p->next;}return num;
}template<class temp>
struct binnode
{temp data;binnode* leftchild;binnode* rightchild;
};template<class temp>
class bintree
{
private:void create(binnode<temp>*& r, temp data[], int i, int n);void release(binnode<temp>* r);
public:binnode<temp>* root;bintree(temp data[], int n);void linkstack_node_root_path(temp target);bool linkstack_search_path(temp target, binnode<temp>*& r, linkstack<binnode<temp>>& stk);~bintree();
};template<class temp>
void bintree<temp>::create(binnode<temp>*& r, temp data[], int i, int n)
{if (i <= n && data[i - 1].existence != 0){r = new binnode<temp>;r->data = data[i - 1];r->leftchild = NULL;r->rightchild = NULL;create(r->leftchild, data, 2 * i, n);create(r->rightchild, data, 2 * i + 1, n);}
}template<class temp>
bintree<temp>::bintree(temp data[], int n)
{create(this->root, data, 1, n);
}template<class temp>
void bintree<temp>::release(binnode<temp>* r)
{if (r != NULL){release(r->leftchild);release(r->rightchild);delete r;}
}template<class temp>
bintree<temp>::~bintree()
{release(this->root);
}template<class temp>
void bintree<temp>::linkstack_node_root_path(temp target)
{linkstack<binnode<temp>>stk;linkstack_search_path(target, this->root, stk);if (stk.empty())cout << target << "未能找到目标" << endl;else{cout << target << "结点到根节点的路径为:" << endl;binnode<temp>out;while (!stk.empty()){out = stk.gettop();if (stk.getsize() == 1)cout << out.data;elsecout << out.data << "->";stk.pop();}cout << endl;}
}template<class temp>
bool bintree<temp>::linkstack_search_path(temp target, binnode<temp>*& r, linkstack<binnode<temp>>& stk)
{if (r == NULL)return false;stk.push(*r);if (r->data == target)return true;else if (linkstack_search_path(target, r->leftchild, stk))return true;else if (linkstack_search_path(target, r->rightchild, stk))return true;stk.pop();return false;
}int main()
{system("color 0A");student stu[5] = { {1,"zhang"},{2,"wang"},{3,"li"},{4,"zhao"},{5,"liu"} };bintree<student>tree(stu, 5);student stu1(1, "zhang"), stu2(5, "liu"), stu3(6, "cao");tree.linkstack_node_root_path(stu1);tree.linkstack_node_root_path(stu2);tree.linkstack_node_root_path(stu3);return 0;
}
2.3运行效果:

相关文章:
北邮22信通:二叉树显示路径的两种方法 递归函数保存现场返回现场的实例
北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 获取更多文章 请访问专栏~ 北邮22信通_青山如墨雨如画的博客-CSDN博客 一.讲解 要想实现二叉树的路径显示,我们要按照…...
vue 3 第二十八章:组件十二(组件的v-model、多v-model)
文章目录 1. 基本使用2. 使用conputed实现3. v-model 的参数4. 多 v-model 的使用5. v-model 修饰符 在 Vue 3 中, v-model 指令的使用更加灵活,可以绑定任意属性和事件。例如,我们可以使用 v-model:checked 指令来绑定单选框或复选框的 c…...
LCD 显示
概述 LCD显示控制模块接收 MCU 送过来的数据,按一定规律储存在显示 RAM 中,并根据显示 RAM 中的数据驱动 LCD 显示屏来实现期望的字符显示功能。 主要特点: ⚫ 最大支持 840 、 642 、 444 的显示段数 ⚫ 1/3bias 、 1/4bia s ⚫ 16 级灰度可…...
互联网医院开发|在线问诊系统架构设计功能有哪些?
互联网医院会增加更多的医疗业务,电话问诊、视频问诊、个性化的医疗套餐等,未来互联网医院会建成围绕健康主题的深度大数据平台和多元化医疗服务生态体系,丰富人工智能、物联网等应用场景,为用户提供更好的服务体验、更低的成本、…...
数据安全运营有效管理-数据安全复合治理框架和模型解读(1)
数据治理,数据安全治理行业在发展,在实践,所以很多东西是实践出来的,哪有什么神仙理论指导,即使有也是一家之说,但为了提高企业投产比,必要的认知是必须的,落地运营管理水平差异直接决定产品和项目是否可持续性,当前和未来更需要专业和有效创新。数据安全治理要充分考…...
【刷题之路】LeetCode 面试题 03.02. 栈的最小值
【刷题之路】LeetCode 面试题 03.02. 栈的最小值 一、题目描述二、解题1、方法1——“辅助栈”1.1、思路分析1.2、代码实现 一、题目描述 原题连接: 面试题 03.02. 栈的最小值 题目描述: 请设计一个栈,除了常规栈支持的pop与push函数以外&am…...
如何处理图片排重(精准排重,相似排重)
图片相似度对比 1、需求 假如有一个图片池,存有1亿图片。给一张目标图片,在图片池中做匹配。 判断一张图片是否在图片池中出现过。(完全一样)判断有没有相似的出现过。比如两张图相似度90,两张图片是在描述一件事情。 …...
盐城北大青鸟“北大青鸟杯”IT精英挑战赛设中心评审隆重开赛
为积极响应北大青鸟总部开展第十届“北大青鸟杯”全国IT精英挑战赛的号召,成就学员们的IT梦想,“北大青鸟杯”IT精英挑战赛(设计组)盐城卓晨中心评审于2023年5月25日下午1:00在人才大厦306教室正式开赛! 赛前&a…...
Pluma 插件管理框架
1. 概述 Pluma 是一个用 C 开发的可用于管理插件的开源架构,其官网地址为:http://pluma-framework.sourceforge.net/。该架构是个轻量级架构,非常易于理解。 Pluma 架构有以下基本概念: 1)插件的外在行为体现为一个…...
Leetcode11 盛最多水的容器
Leetcode11 盛最多水的容器 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/container-with-most-water/description 博主Github:https://github.com/GDUT-Rp/LeetCode 题目: 给定一个长度为 n…...
Java
FileOutputStream写数据的3种方式 void write(int b) //一次写一个字节的数据 void write(byte[] b) //一次写一个字节数组数据 void write(byte[] b, int off,int len) //一次写一个字节数组的部分数据 参数一:数组;参数二:起始索引 0;参数三:个数换行: windows:“\r\n” lin…...
第十四章行为性模式—策略模式
文章目录 命令模式解决的问题结构实例存在的问题适用场景 JDK源码解析 行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式…...
Leaflet基本用法
使用 阿里云地理工具 获取相应的地理JSON数据,用于对地图边界绘制。 如何使用leaflet? 这里用HTML5进行操作; 因为我是用的是Leaflet库,所以要引入JavaScript 和 CSS 文件(可参考官网https://leafletjs.com/&#x…...
Unity | HDRP高清渲染管线学习笔记:示例场景解析
目录 一、HDRP入门 1.HDRP设置 1.1 HDRP配置文件中的全部设置项 1.1.1 Rendering下的Lit Shader Mode 1.1.2 Lighting 下的Volumetrics(体积光)和Screen Space Reflection(屏幕空间反射) 2.离线渲染VS实时渲染 3.Volume组件 …...
【Netty】Netty 编码器(十三)
文章目录 前言一、MessageToByteEncoder 抽象类二、MessageToMessageEncoder 抽象类总结 前言 回顾Netty系列文章: Netty 概述(一)Netty 架构设计(二)Netty Channel 概述(三)Netty ChannelHan…...
Netty和Tomcat的区别、性能对比
文章目录 一、Netty和Tomcat有什么区别?二、为什么Netty受欢迎?三、Netty为什么并发高 ? 一、Netty和Tomcat有什么区别? Netty和Tomcat最大的区别就在于通信协议,Tomcat是基于Http协议的,他的实质是一个基…...
chatgpt赋能python:Python函数调用局部变量-深入了解
Python函数调用局部变量-深入了解 函数调用局部变量是Python中的一个重要概念,特别是在大型项目中,其中多个函数共享相同变量时。在本文中,我们将深入探讨Python函数调用局部变量,并为您介绍一些实用技巧。 什么是Python函数调用…...
Android 12.0 NavigationBarView 导航栏 左边显示的修改
1.概述 在12.0定制化开发中,要求导航栏左边显示的定制化,这时需要了解导航栏的显示控制方向,然后修改显示方向 在10.0以后关于导航栏显示位置都是在DisplayPolicy.java中处理的所以查询相关的设置方法,然后修改导航栏显示方向2.NavigationBarView 导航栏 左边显示的修改的…...
Mybatis源码细节探究:二级缓存Cache对象是在什么时候创建的?
给自己的每日一句 不从恶人的计谋,不站罪人的道路,不坐亵慢人的座位,惟喜爱耶和华的律法,昼夜思想,这人便为有福!他要像一棵树栽在溪水旁,按时候结果子,叶子也不枯干。凡他所做的尽…...
【数据库】无效数据:软件测试对无效数据的处理
目录 一、无效数据的常见场景 (1)测试阶段 (2)测试方法 二、无效数据的概念 三、无效数据的影响 四、无效数据的识别 五、无效数据的处理方法 (1)拒绝无效数据 ① 拒绝无效数据的概念 ② 拒绝…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...
02.运算符
目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&:逻辑与 ||:逻辑或 !:逻辑非 短路求值 位运算符 按位与&: 按位或 | 按位取反~ …...
