北邮22信通:二叉树显示路径的两种方法 递归函数保存现场返回现场的实例

news2024/12/25 8:56:20

北邮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,不是9
		return 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;
			else
				cout << 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;
			else
				cout << 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;
			else
				cout << 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;
			else
				cout << 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运行效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/567037.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

gitbook在centos上安装

1&#xff09;官网下载Node.js的Linux64位的二进制包:Download | Node.js 或者在线下载&#xff1a; wget https://nodejs.org/dist/v12.16.1/node-v12.16.1-linux-x64.tar.xz ​​2)到指定目录​解压 cd /opt/gitbook tar -xJf node-v12.16.1-linux-x64.tar.xz mv node-…

记录--按钮级别权限怎么控制

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 最近的面试中有一个面试官问我按钮级别的权限怎么控制&#xff0c;我说直接v-if啊&#xff0c;他说不够好&#xff0c;我说我们项目中按钮级别的权限控制情况不多&#xff0c;所以v-if就够了&#xff…

wifiWG233移植

驱动的移植 交叉编译WIFI原厂固件驱动 根据网上资料&#xff0c;和官方文档编译成功。 修改Makefile 修改交叉编译环境 执行 make 编译成功&#xff0c;生成88x2bu.ko 加载原厂驱动 Insmod 88x2bu.ko 生成wlan0 Hostapd工具移植生成可连接热点AP 安装libnl库 使用命令tar …

ApiKit 接口调用、自动化测试工具

作为一位后端开发&#xff0c;我们平时经常需要维护API文档、对API接口进行调试、有时候还得Mock数据。Postman虽然作为接口调试工具非常好用&#xff0c;但是对于维护API文档这类工作却不太合适。今天给大家推荐一款功能更强大的工具ApiKit&#xff0c;足以满足我们对API的各种…

如何清除电脑缓存?分享3个有效的方法!

案例&#xff1a;我发现我的电脑运行速度越来越慢&#xff0c;影响使用体验。朋友说可能是我没有及时清理电脑缓存文件所致&#xff0c;那如何清理缓存的文件&#xff1f; 【我想通过清理电脑缓存文件的方法&#xff0c;提高我电脑运行的速度&#xff0c;但是我不知道具体的操…

如何利用Citespace和vosviewer既快又好地写出高质量的论文及快速锁定热点和重点文献进行可视化分析?

基于Citespace和vosviewer文献计量学可视化SCI论文高效写作方法 CiteSpace是什么&#xff1f; 简单来说&#xff0c;它一款通过将国内外文献进行可视化分析来帮助你了解一门学科前世今生的软件。 面对成千上万篇的文献&#xff0c;怎样才能快速锁定自己最感兴趣的主题及科学…

取代 Docker Desktop?Podman Desktop 发布 GA 版本 1.0

Podman&#xff08;POD MANager&#xff09;是一个跨平台的容器管理工具&#xff0c;可用于管理容器、镜像、卷以及以容器组形式存在的 Pod。Podman 可以在 Linux 上直接运行容器&#xff0c;但在像 macOS 和 Windows 这样的平台&#xff0c;是通过虚拟机间接运行容器。 Podma…

「实在RPA·电商数字员工」契合电商数智转型需求

一、为什么说电商数智化转型很重要&#xff1f; 如今&#xff0c;电商发展速度惊人&#xff0c;并且已经取代了实体店购物的时代。在众多新型的消费方式下&#xff0c;各式的电商行业如何运作&#xff0c;并且在短时间内完成各项任务&#xff0c;提升人们的生活质量。人们生活…

django admin后台列表页、修改/详情页图片预览功能

目录 一、admin后台列表页的图片预览功能 二、admin后台修改/详情页图片预览功能 1&#xff0c;添加html前端代码 2、在admin.py文件中添加以下代码&#xff1a; 1.列表页图片问题&#xff1a;在admin列表页中&#xff0c;直接在list_display中填写图片字段时在列表页展示的…

YOLOv5从训练到移植

一、图像采集和标注 图像采集 覆盖所有的数据目标&#xff0c;不同场景&#xff08;视角、光照、可能的干扰&#xff09;、距离、运动、背景等&#xff0c;用深度和广度摄像头都行。 若兼顾效率和准确率&#xff0c;可以用迁移学习思路训练&#xff0c;则不同场景下采集的图…

系统方面对文件的打开,读写,关闭

系统方面对文件的操作 1. 系统方面打开文件的函数2. 系统方面对文件的写入3. 系统方面对文件的读取4. 关闭文件close 1. 系统方面打开文件的函数 open函数得到一个指定文件的文件描述符&#xff0c;如果出现错误则返回-1。open函数需要传入一个文件路径和操作模式&#xff0c;…

高德地图AMap.MouseTool插件多次测距不能清除bug

AMap.MouseTool插件是一个很有用的插件&#xff0c;可以在地图上画折线测量距离&#xff0c;也可以在地图上画区域测量面积&#xff0c;这些在客户的一些高级需求里经常出现&#xff0c;最近使用出现了bug&#xff0c;此bug在官网的示例里也能重现 官网demo上重现步骤如下图&a…

剑指 Offer 58 - I. 翻转单词顺序

剑指 Offer 58 - I. 翻转单词顺序 题目&#xff1a; 输入一个英文句子&#xff0c;翻转句子中单词的顺序&#xff0c;但单词内字符的顺序不变。为简单起见&#xff0c;标点符号和普通字母一样处理。例如输入字符串"I am a student. “&#xff0c;则输出"student. a …

Spring Tool Suite(STS)初始化配置记录

目录 1.前言 2.STS安装 3.STS配置 3.1.SpringToolSuite4.ini 3.2、配置maven 3.3.配置jdk 3.4.全局编码设置 3.5.字体配置 3.6.设置自动提示 4. Spring插件 4.1.MyBatipse--mybatis插件 4.2.Spark Builder Generator 4.3.Properties Editor 4.4.Checkstyle 4.5.…

【MySQL】数据库的基本操作

&#x1f3e0; 大家好&#xff0c;我是 兔7 &#xff0c;一位努力学习C的博主~&#x1f4ac; &#x1f351; 如果文章知识点有错误的地方&#xff0c;请指正&#xff01;和大家一起学习&#xff0c;一起进步&#x1f440; &#x1f680; 如有不懂&#xff0c;可以随时向我提问&…

Smoothieware_best-for-pnp 工程文件编译选项含义整理

文章目录 Smoothieware_best-for-pnp 工程文件编译选项含义整理概述arm-none-eabi-gcc 的编译选项含义整理 - S(汇编)文件arm-none-eabi-gcc 的编译选项含义整理 - C文件arm-none-eabi-gcc 的编译选项含义整理 - CPP文件库的打包arm-none-eabi-gcc 的编译选项含义整理 - C文件 …

Python入门教程+项目实战-12.3节-使用字典进行格式化

目录 12.3.1 字符串的格式化 12.3.2 使用字典进行格式化 12.3.3 格式化操作方法的优缺点 12.3.4 知识要点 12.3.5 系统学习python 12.3.1 字符串的格式化 在9.4节介绍了字符串的格式化&#xff0c;我们先来回顾下字符串格式化的定义&#xff0c;以及主要的格式化方法&…

万字长文详述ClickHouse在京喜达实时数据的探索与实践 | 京东云技术团队

1 前言 京喜达技术部在社区团购场景下采用JDQFlinkElasticsearch架构来打造实时数据报表。随着业务的发展 Elasticsearch开始暴露出一些弊端&#xff0c;不适合大批量的数据查询&#xff0c;高频次深度分页导出导致ES宕机、不能精确去重统计&#xff0c;多个字段聚合计算时性能…

从零开始的python教程:全面又好用的学习资料

Hi&#xff0c;大家好&#xff0c;我是蛋糕 最近因为接连带过一些训练营和成长营&#xff0c;也是可以与各位小伙伴进行更多的讨论&#xff0c;发现各位小伙伴最近也是迫切的想要学习一些新的技能&#xff0c;其中呼声最高的可能就是Python了&#xff0c;当然理由也是很多啦&a…

LeetCode 84 柱状图中最大的矩形

题目&#xff1a; 给定n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 示例 1: 输入&#xff1a;heights [2,1,5,6,2,3] 输出&#xff1a;10 解释&#xf…