数据结构与算法学习:二叉树的后序遍历的递归与非递归实现,以及非递归实现中的流程控制的说明。

这篇具有很好参考价值的文章主要介绍了数据结构与算法学习:二叉树的后序遍历的递归与非递归实现,以及非递归实现中的流程控制的说明。。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

需求二叉树:

数据结构与算法学习:二叉树的后序遍历的递归与非递归实现,以及非递归实现中的流程控制的说明。

采用二叉树后序遍历非递归算法。设置一个指针p初始指向树根,p先入栈,而后使得p指向它的左孩子p->firstchild,重复操作,使得每个左孩子都依次入栈,同时初始化一个Treenode*类型的指针pre,这个指针是后序前驱,这个后序前驱用以区分为已访问过的结点和未访问过的结点。

由于栈顶元素一定是某一子树的根,那么先假设p==S.top()我们把叶子结点等价为左右孩子都为空的子树的根作为分析时的假设,想要访问栈顶元素那么要么右子树为空,要么右子树被访问完为空好办,核心的流程控制就在于右子树访问完这里的问题,根据后续遍历的性质又知道,因为先前设置pre为上一步刚访问过的结点,即后序前驱,如果右子树被访问完那么就意味着p->nextchild==后序前驱,而这个后序前驱就是pre,要是p=p->nextchild,而后右设置pre=p,而p->nextchild==pre...那么就会在pre那里死循环。所以,能让p=p->nextchild;的条件就是(p->nextchild!=NULL&&p->nextchild!=后序前驱)若p->nextchild!=NULL不和后一个条件相与会形成访问某一个结点的右子树的死循环。

后序遍历非递归算法的流程控制较为复杂,以上为流程控制中条件判断的确定方法,下面给出算法流程:

①沿着根的左孩子依次入栈

②直到左孩子为空读栈顶元素若其右孩子不空且未被访问过将右子树转执行①否则栈顶元素出栈并访问。

”tree.hpp":

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdbool.h>
#include <iostream>
#include <stdlib.h>
#include <ctime>
#include <stack>
#include<queue>
using namespace std;


class Treenode
{
	friend class Bitree;
public:
	
	Treenode();
	Treenode(char a);
	//Treenode(char c);
	Treenode& setnode(char a)
	{
		this->val = a;
		return *this;
	}

	void setfirstchild(Treenode* a);
	void setnextchild(Treenode* a);
	void setrtag(bool a);
	void setltag(bool a);
	char getval();
	Treenode& getfirstchild();
	Treenode& getnextchild();

private:
	
	char val;//数据部分
	Treenode* firstchild;
	Treenode *nextchild;//同一化的树的存储
	bool ltag , rtag ;//0表示有左或右孩子,1表示该结点没有左或右孩子,且此链域是线索

};

Treenode& Treenode::getfirstchild()
{
	return *this->firstchild;
}
Treenode& Treenode::getnextchild()
{
	return *this->nextchild;
}
char Treenode::getval()
{
	return this->val;
}
void Treenode::setfirstchild(Treenode* a)
{
	this->firstchild = a;
}
void Treenode::setnextchild(Treenode *a)
{
	this->nextchild = a;
}

void Treenode::setltag(bool a)
{
	this->ltag = a;
}
void Treenode::setrtag(bool a)
{
	this->rtag = a;
}
Treenode::Treenode(char a)
{
	this->val = a;
	if (this->firstchild != NULL)
	{
		delete this->firstchild;
	}
	this->firstchild = NULL;
	if (this->nextchild != NULL)
	{
		delete this->nextchild;
	}
	this->nextchild = NULL;
	this->ltag = false;
	this->rtag = false;
}
Treenode::Treenode()
{
	this->val = '#';
	if (this->firstchild != NULL)
	{
		delete this->firstchild;
	}
	this->firstchild = NULL;
	if (this->nextchild != NULL)
	{
		delete this->nextchild;
	}
	this->nextchild = NULL;
	this->ltag = false;
	this->rtag = false;
}



class Bitree
{
	friend class Treenode;
public:
	Bitree()
	{
		this->root = new(class Treenode);
	}
	Treenode& setroot(Treenode* a);

	void visit(Treenode* a);
	Treenode* getroot()
	{
		return this->root;
	}
	

	
	int getcount()
	{
		return this->count;
	}


	void postorder_traversal(Treenode* t);//后序遍历
	void postorder_nonrecursion_traversal();//后序非递归算法
private:
	Treenode* root;
	int count = 0;
};

void Bitree::postorder_traversal(Treenode* t)//后序遍历
{
	if (t == NULL)
		return;
	postorder_traversal(t->firstchild);
	postorder_traversal(t->nextchild);
	this->visit(t);
}
void Bitree::postorder_nonrecursion_traversal()//后序非递归算法
{
	stack<Treenode*> S;
	Treenode* p = this->root;
	Treenode* pre = NULL;//最近访问过的结点,后序前驱
	while (p || !S.empty())
	{
		if (p)
		{
			S.push(p);
			p = p->firstchild;
		}
		else 
		{
			p = S.top();//只有当前p为空才使它指向栈顶元素
			if (p->nextchild && p->nextchild != pre)//为什么要设置一个最近访问过的结点r?
				p = p->nextchild;//上面的p->nextchile!=r用于防环
			else
			{
				p = S.top();
				S.pop();
				this->visit(p);
				pre= p;
				p = NULL;//这一点不容易想到,比较容易直接给它设为指向栈顶元素,还容易不断地重复逻辑判断,流程控制较复杂

			}

		}
	}

}


Treenode& Bitree::setroot(Treenode* a)
{
	
	this->root = a;
	return *this->root;
}
void Bitree::visit(Treenode*a)
{
	if (a->val != '#')
	{
		cout << a->val;
		this->count++;
	}

}


	

"源文件.cpp":

#define _CRT_SECURE_NO_WARNINGS 1

#include	"tree.hpp"



int main()
{
	

	//先创建空树再遍历赋值
	Bitree T;
	Treenode m1('A');
	Treenode m2('B');
	Treenode m3('C');
	Treenode m4('D');
	Treenode m5('E');
	Treenode m6('F');
	Treenode m7('G');

	T.setroot(&m1);
	m1.setfirstchild(&m2);
	m1.setnextchild(&m3);

	m2.setfirstchild(&m4); 
	m2.setnextchild(&m5);
	m3.setfirstchild(&m6);
	m3.setrtag(true) ;
	m4.setnextchild(&m7);
	//cout << m4.getnextchild().getval();
	m4.setrtag(true);
	m5.setrtag(true);
	m5.setrtag(true);
	m6.setrtag(true);
	m6.setrtag(true);
	m7.setrtag(true);
	m7.setrtag(true) ;


	cout << "后序遍历序列为:";
	T.postorder_nonrecursion_traversal();
	cout << endl;
	cout << "树中结点数为:" << T.getcount() << endl;
	
	



	system("pause");
	return 0;
}

代码测试:

数据结构与算法学习:二叉树的后序遍历的递归与非递归实现,以及非递归实现中的流程控制的说明。文章来源地址https://www.toymoban.com/news/detail-421539.html

到了这里,关于数据结构与算法学习:二叉树的后序遍历的递归与非递归实现,以及非递归实现中的流程控制的说明。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构与算法】二叉树的知识讲解

    目录  一,二叉树的结构深入认识  二,二叉树的遍历  三,二叉树的基本运算 3-1,计算二叉树的大小 3-2,统计二叉树叶子结点个数 3-3,计算第k层的节点个数 3-4,查找指定值的结点         二叉树是不可随机访问的,二叉树的结构是通过双亲结点与孩子结点之间的连接进

    2024年02月08日
    浏览(29)
  • 【数据结构】【算法】二叉树、二叉排序树、树的相关操作

    树结构是以分支关系定义的一种层次结构,应用树结构组织起来的数据,逻辑上都具有明显的层次关系。 操作系统中的文件管理系统、网络系统中的域名管理、数据库系统中的索引管理等都使用了树结构来组织和管理数据。 树 Tree 是由n个节点组成的有限集合。在任意一颗非

    2024年02月04日
    浏览(40)
  • 【数据结构与算法】力扣:二叉树的层序遍历

    给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。 示例1: 输入:root = [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]] 示例 2: 输入:root = [1] 输出:[[1]] 示例 3: 输入:root = [] 输出:[] 来源:力扣(LeetCode) 链接:https://leetcode.cn/p

    2024年02月13日
    浏览(36)
  • 数据结构与算法----详解二叉树的遍历(迭代、递归)

    ❤️ 作者简介 :大家好我是小鱼干儿♛是一个热爱编程、热爱算法的大三学生,蓝桥杯国赛二等奖获得者 🐟 个人主页 :https://blog.csdn.net/qq_52007481 ⭐ 个人社区 :【小鱼干爱编程】 🔥 算法专栏 :算法竞赛进阶指南 💯 刷题网站 :虽然市面上有很多的刷题网站,但是里面

    2024年01月24日
    浏览(41)
  • 数据结构与算法之二叉树: Leetcode 111. 二叉树的最小深度 (Typescript版)

    二叉树的最小深度 https://leetcode.cn/problems/minimum-depth-of-binary-tree/ 描述 就 给定一个二叉树,找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明:叶子节点是指没有子节点的节点。 示例 1 示例 2 提示 树中节点数的范围在 [0, 1 0 5 10^5 1 0 5 ] 内

    2024年02月06日
    浏览(36)
  • 【算法与数据结构】236、LeetCode二叉树的最近公共祖先

    所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。    思路分析 : 根据定义,最近祖先节点需要遍历节点的左右子树,然后才能知道是否为最近祖先节点。 那么这种需求是先遍历左右节点,然后遍历中间节点,属于左右中的后序遍历模式 。因此

    2024年02月09日
    浏览(30)
  • 数据结构与算法学习:二叉树的后序遍历的递归与非递归实现,以及非递归实现中的流程控制的说明。

    需求二叉树: 采用二叉树后序遍历非递归算法。设置一个指针p初始指向树根,p先入栈,而后使得p指向它的左孩子p-firstchild,重复操作,使得每个左孩子都依次入栈,同时初始化一个Treenode*类型的指针 pre,这个指针是后序前驱,这个后序前驱用以区分为已访问过的结点和未

    2023年04月22日
    浏览(37)
  • 数据结构——基于二叉树的表达式求值算法

    1.输入一个表达式(表达式中的数均小于10的正整数),利用二叉树来表示该表达式,创建表达式数,然后利用二叉树的遍历操作求表达式的值。 2.输入要求:多组数据,每组数据1行,为一个表达式,表达式以“=”结尾。当输入只有一个“=”时,输入结束。 3.输出要求:每组

    2024年02月04日
    浏览(34)
  • 【算法与数据结构】222、LeetCode完全二叉树的节点个数

    所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。    思路分析 :利用层序遍历,然后用num++记录节点数量。其他的例如递归法和迭代法也是如此。    层序遍历程序如下 : 复杂度分析: 时间复杂度: O ( n ) O(n) O ( n ) 。 空间复杂度: O ( n )

    2024年02月15日
    浏览(35)
  • 数据结构与算法—二叉树数组表示(ArrayBinTree)、二叉树的链式表示(LinkedBinTree)的基于C++模板代码实现

    1、二叉树的顺序表示:ArrayBinTree.h 二叉树的顺序表示法操作方便,但缺点是容易造成存储空间浪费。 这是一个用数组实现的二叉树类模板。它可以创建一个空树,也可以在指定的位置插入结点并设置结点的值,可以删除子树,并支持逐层遍历。使用该类时,需要提供一个元

    2024年02月06日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包