【数据结构】中序线索化二叉树后实现一个迭代器来遍历二叉树

【数据结构】迭代器实现二叉树的中序遍历 迭代器 template struct __TreeIterator { typedef BinTreeNode Node; typedef __TreeIterator Self; __TreeIterator() {} __TreeIterator(Node* node) :_node(node) {} Ref operator*() { assert(_node); 阅读详情

1.创建二叉树的结点

#pragma once
#include<iostream>
#include<stack>
using namespace std;
enum PointerTag
{
	THREND,
	LINK,
};
template<class T>
struct BinaryTreeThdNode
{
	typedef BinaryTreeThdNode<T> Node;
	BinaryTreeThdNode(T data)
		:_data(data), _left(NULL), _right(NULL),_father(NULL), _leftTag(LINK), _rightTag(LINK)
	{}
	T _data;
	Node* _left;
	Node* _right;
	Node* _father;     //为后续线索化的遍历设置的父指针,此处可以忽略
	PointerTag _leftTag;
	PointerTag _rightTag;
};

2.创建二叉树

template<class T>
class BinaryTreeThd
{
public:
	typedef BinaryTreeThdNode<T> Node;
	typedef TreeIterator<T, T*, T&> Iterator;
	BinaryTreeThd()
	{}
	BinaryTreeThd(T* arr, size_t size, T invalid)   //非递归创建树

	{
		stack<Node*> s;
		size_t index = 0;
		Node* cur = NULL;
		while (index < size)
		{
			while (index < size && (arr[index] != invalid))
			{
				if (index == 0)   //根节点特殊处理
				{
					cur = new Node(arr[index++]);
					_root = cur;
				}
				else
				{
					cur->_left = new Node(arr[index++]);   //创建左结点
					Node* tmp = cur;
					cur = cur->_left;
					cur->_father = tmp;
				}
				s.push(cur);
			}
			index++;
			Node* top = s.top();
			s.pop();
			if ((index<size)&&(arr[index] != invalid))
			{
				cur = top;
				cur->_right = new Node(arr[index++]);   //创建右节点
				Node* tmp = cur;
				cur = cur->_right;
				cur->_father = tmp;
				s.push(cur);
			}
		}
	}
private:
    Node* _root;
}

/*******************中序线索化递归实现********************/
	void InorderThreading()
	{
		Node* prev = NULL;
		_InorderThreading(_root, prev);
	}
	void _InorderThreading(Node* cur,Node*& prev)
	{
		if (cur == NULL)
			return;
		_InorderThreading(cur->_left, prev);        //递归线索化左子树
		if (cur->_left == NULL)
		{
			cur->_leftTag = THREND;
			cur->_left = prev;
		}
		if (prev && (prev->_right == NULL))
		{
			prev->_rightTag = THREND;
			prev->_right = cur;
		}
		prev = cur;
		_InorderThreading(cur->_right, prev);   //递归线索化右子树

		
	}
/**************中序线索化非递归实现**********************/
void InorderThreading()
	{
		Node* cur = _root;
		Node* prev = NULL;
		stack<Node*> s;
		while (cur || !s.empty())
		{
			while (cur)
			{
				s.push(cur);
				cur = cur->_left;
			}
			Node* top = s.top();
		
			if ((top->_left == NULL))
			{
				top->_left = prev;
				top->_leftTag = THREND;
			}
			
			if (prev&&(prev->_right == NULL))
			{
				prev->_rightTag = THREND;
				prev->_right = top;
			}
			prev = top;
			if (top->_right != NULL)
				cur = top->_right;
			s.pop();
			
		}
	}
3.迭代器部分

template<class T,class Ptr,class Ref>
class TreeIterator
{
public: 
	typedef TreeIterator<T, Ptr, Ref> self;
	typedef TreeIterator<T, T*, T&> Iterator;
	typedef BinaryTreeThdNode<T> Node;
	TreeIterator(Node* p)
		:ptr(p)
	{}
	TreeIterator()
	{}
	self& operator++()
	{
		if (ptr->_rightTag == THREND)
		{
			ptr = ptr->_right;
		}
		else if (ptr->_rightTag == LINK)
		{
			Node* tmp = ptr->_right;
			while (tmp&&tmp->_leftTag == LINK)
			{
				tmp = tmp->_left;
			}
			ptr = tmp;
		}
		return *this;
	}
	bool operator!=(Iterator it)
	{
		return !(ptr == it.ptr);
	}
	Ref operator*()
	{
		return ptr->_data;
	}
private:
	Node* ptr;
};
Iterator Begin()
	{
		Node* cur = _root;
		while (cur->_leftTag)
			cur = cur->_left;
		return Iterator(cur);
	}
	Iterator End()
	{
		Node* cur = _root;
		while (cur!=NULL)
		{
			cur = cur->_right;
		}
		return Iterator(cur);
	}
4.测试

void TestInOrderIter()
{
	int array[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
	int array1[15] = { 1, 2, '#', 3, '#', '#', 4, 5, '#', 6, '#', 7, '#', '#', 8 };
	BinaryTreeThd<int> bt(array, 10, '#');
	bt.InorderThreading();
	BinaryTreeThd<int>::Iterator it;
	for (it = bt.Begin(); it != bt.End();++it)
	{
		cout << *it << " ";
	}
	cout << endl;
	BinaryTreeThd<int>bt1(array1, 15, '#');
	bt1.InorderThreading();
	BinaryTreeThd<int>::Iterator it1;
	for (it1 = bt1.Begin(); it1 != bt1.End(); ++it1)
	{
		cout << *it1 << " ";
	}
	cout << endl;
}





(C++)二叉树的线索化 / 线索二叉树 二叉树的线索化 线索二叉树 阅读详情

相关推荐

Transformer数学推导——Q38 旋转位置编码(RoPE)的复数形式 对注意力分数的几何影响分析

RoPE 的复数形式为自然语言处理中的位置编码提供了创新且有效的解决方案。通过深入的数学理论分析,明确了其对注意力分数的几何影响及在捕捉位置信息方面的优势。在 LLM 的实际应用中,RoPE 复数形式在多个任务和场景中展现出强大的性能,特别是在处理长序列文本时,能够有效捕捉长距离依赖、缓解位置编码局限性并提升处理效率。然而,RoPE 复数形式也面临计算复杂度高、超参数调整困难和位置信息平衡等挑战。通过合理的优化策略和与其他技术的结合,有望进一步提升其性能。

墨顿随笔 1420

线索二叉树建立

今天学习了线索二叉树的建立,于是走了一遍代码 #include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> using namespace std; /* 二叉树线索存储结构的定义 Link=0;代表指向左右孩子的指针 Thread=1, 代表指向前驱或者后继的...

Zyong139064359的博客 510

Unity2D像素刀光实现:粒子方向控制与像素级渲染规范

像素风游戏中的刀光特效并非普通粒子动画,而是需严格遵循像素艺术原理的视觉暂留模拟。其核心在于将‘瞬时切割感’转化为程序可执行的渲染逻辑:通过禁用纹理滤波保障1:1像素锐度,绑定刀锋向量控制粒子运动方向,限定≤0.15秒生命周期匹配人眼暂留阈值,并采用Stretched Billboard实现动态拉伸拖影。该方案兼顾美术语义(如直劈、横扫、突刺)与工程约束(Sorting Layer分层、对象池复用、单粒子GPU优化),广泛适用于Unity2D平台的动作反馈系统,尤其适配《空洞骑士》《死亡细胞》类高节奏像素R

weixin_32390647的博客 284

枚举常见用法

1.枚举的定义枚举的定义方法和结构体的定义方法是类似的,结构体使用的关键字是struct,而枚举使用的关键字是enum.应用如下: enum spectrum_tag{red,orange,yellow,green,blue}; enum spectrum_tag color;//用刚才定义的枚举类型定义了一个变量名color,这个变量名的值只能是red,orange等等。2.枚举的

Disco_very的博客 1343

从分立到集成:深入解析Buck电路的核心模块与设计权衡

本文深入解析Buck电路的核心模块与设计权衡,从分立到集成方案的优缺点对比。详细探讨Buck电路的高效能量转换、小型化设计及灵活电压调节能力,并结合实际案例分享分立方案中的PWM生成、反馈环路设计及保护电路优化经验,为工程师提供实用设计参考。

weixin_29306317的博客 225

Zemax:初学者的混合模式

光线以序列模式开始,然后接近非序列组件的入口端口。到达入口端口后,光线以非序列模式传播,然后接近出口端口。光线离开出口端口后,我们又回到序列模式。在此博客中,使用混合模式的示例将演示根据您自己的需要复制此工作流程所需的基本设置,以及一些有用的技巧。非序列组件表面类型必须在序列模式和非序列模式下定义。为了定义非序列组件的几何形状,请转到设置->编辑器->非序列,单击非序列编辑器。一旦我们进入非序列组件编辑器:表面 2 上的组件组,找到一个对象类型并进行定义。它能让您兼具序列模式的精确性和非序列模式的灵活性。

jkh920184196的博客 1342

二叉树的非递归中序遍历以及二叉搜索树的迭代器

二叉树的非递归中序遍历 中序序列为左根右,因此用栈模拟这一过程,就是从当前子树根结点出发,一直往左走,把沿途结点全部入栈,直到最左边,对于最左边的结点来说,他没有左孩子,根据“左根右”的顺序,这时需要从堆栈中弹出这个结点,访问它(这里表现为加到res数组中)如果它有右孩子,就往右边走,然后对于这棵子树重复上面的操作。 所以代码如下: /** * Definition for a bina...

wwxy1995的博客 383

新手也能玩转!用Panosim+MATLAB/Simulink搭建你的第一个智能驾驶仿真场景(保姆级图文)

本文为新手提供了使用Panosim和MATLAB/Simulink搭建智能驾驶仿真场景的详细教程。从环境准备、基础场景创建到仿真模型构建,一步步指导用户完成第一个智能驾驶仿真项目,帮助零基础用户快速上手并体验智能驾驶仿真的乐趣。

weixin_29090089的博客 185

二叉树的线索化

测试环境:VS2010  一、线索二叉树的引入         二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历。用二叉树作为存储结构时,取到一个节点,只能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继。               为了保存这种在遍历中需要的信息,我们利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息。

snow_5288的博客 3215

OpenClaw 核心命令深度解析:/think high、/reasoning on、/verbose on 功能与实战指南

本文深入解析OpenClaw框架的三大核心命令:/think high实现极限深度推理,突破常规思考瓶颈;/reasoning on提供透明化推理过程,增强决策可信度;/verbose on控制详细输出级别。文章从技术架构、实现原理、配置方法和典型场景四个维度,详细阐述了各命令的功能特性与实战应用,包括法律分析、代码调试和商业决策等复杂场景的最佳实践。同时提供了多级配置方案和资源消耗参考,帮助用户根据任务复杂度灵活调配AI资源,实现效率与深度的最优平衡。

qq_43344878的博客 947

51单片机 驱动有源/无源蜂鸣器+Proteus仿真

51单片机 驱动有源/无源蜂鸣器+Proteus仿真 相关篇《51单片机 Proteus仿真有源蜂鸣器始终不响原因及解决方法》 电路搭建 采用NPN管驱动有源蜂鸣器电路 采用PNP管驱动有源蜂鸣器电路 采用PNP管驱动无源蜂鸣器 采用NPN管驱动无源蜂鸣器 Proteus元器件列表 实例代码 /************************************************************************************* * 实验现象:下载程序

perseverance51博客 2万+

数据结构::线索化二叉树

1、为什么要引入线索化二叉树?       我们知道二叉树是一种非线性结构,当我们遍历二叉树的时候,我们一般的方法是利用递归或者是借助栈来实现非递归,而不管是利用递归还是栈我们知道,它们所用的开销是很大的,即压栈,建立新的栈帧,当有时候我们递归的层次很深的时候,会出现溢出,而且一般递归虽然简单,但是效率比较低。       因此我们就想能不能采取一种方式,可以减小开销,遍历的时候可以一次解决,

海绵宝宝的欧尼~ 的博客 838

2025年5月架构设计师论文真题回顾,附写作技巧、所涉知识点及参考范文(三)

本文主要回顾2025年上半年(2025-5-24)系统架构设计师考试下午论文的题目,同时附带写作技巧、所涉知识点及参考范文。试题三:多模型数据库及应用。

一几文的编程学习笔记。 632

数据结构:二叉树线索化

二叉树线索化:二叉树前序线索化,二叉树中序线索化,二叉树后续线索化,二叉树前序线索化遍历,二叉树中序线索化遍历,二叉树后续线索化遍历,析构,迭代器遍历线索化后的二叉树

peter——wang的博客 1552

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

二叉树线索化

二叉树的线索化可以使得二叉树的非递归遍历不需借助栈或队列这种数据结构,最主要的是可以为之提供迭代器。线索化二叉树有三种方式:前序线索化、中序线索化、后序线索化(后序线索化需要三叉链结构)这里主要讲前序线索化和中序线索化,并为中序线索化提供迭代器。 线索化的思想就是将一颗二叉树遍历转换成有序双向链表进行访问。这样二叉树的节点结构就应该多一个前驱和后继的线索化标志。 节点结构 enum Point

丁香枝上,豆蔻梢头 596

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

C++实现线索二叉树:从数据结构到高效遍历的工程实践

二叉树是计算机科学中处理层次化数据的基础数据结构,广泛应用于数据库索引、文件系统等场景。其核心原理在于通过节点与指针构建非线性关系,以实现高效的数据组织与检索。传统递归遍历存在栈空间开销,而线索化技术通过复用节点的空指针域,将其指向遍历序列中的前驱或后继节点,从而在O(1)空间复杂度下实现线性化访问,极大提升了遍历效率。这项技术在处理大规模、结构稳定且需频繁遍历的树形数据时价值显著,例如在编译器语法树分析或游戏场景管理中。本文以C++工程实践为例,深入探讨了中序线索化的具体实现,包括节点结构设计、递归线索化

ciya3282的博客 322

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

C++类模板实现线索二叉树:优化遍历与查询的高效数据结构

在数据结构与算法领域,二叉树是一种基础且重要的非线性数据结构,广泛应用于文件系统、数据库索引和编译器语法树等场景。其核心原理是通过节点与左右子节点的链接关系组织数据。传统二叉树遍历通常借助栈实现,存在空间开销,且查询节点的直接前驱或后继效率较低。为了优化这一过程,线索二叉树技术应运而生,它通过复用节点的空指针域,将其指向遍历序列中的前驱与后继,从而在几乎不增加存储开销的前提下,实现了O(1)空间复杂度的遍历和快速的前驱后继查询,极大提升了数据结构的工程实践价值。本文结合C++类模板技术,详细解析了线索二叉树

weixin_33728708的博客 403

《大话数据结构》第6章精读:线索二叉树 —— 把空指针变成“线索“的完整实现与分析

不额外分配空间,而是把 n+1 个空指针域变成有意义的线索。用两个标志位的微小代价,换取了 O(1) 空间遍历和 O(1) 查找前驱/后继的能力。把非线性结构(树)转换成了线性结构(双向链表),让遍历变得像链表一样简单。在实际应用中,线索二叉树的思想被广泛借鉴。例如MySQL 的 InnoDB 存储引擎中,B+ 树的叶子节点之间就通过类似"线索"的指针串联起来,以实现高效的范围查询和顺序扫描。理解了线索二叉树,再去理解 B+ 树叶子节点的链表结构,会发现它们有着异曲同工之妙。

2401_87777279的博客 335

线索化二叉树

**线索化:**能够对这颗树进行非递归遍历;能够给这棵树加上迭代器;线索化避免了这棵树遍历时的递归回旋问题,使用一个循环一口气就可以将这棵树访问完毕,可以这么理解,树的本身访问到了叶子节点就出现了断点问题,就要开始递归回旋判断,然而我们使用了线索化以后就相当于将断点问题解决,这就是一条可以直达终点的通路。 可以用两句话概括: A. 如果当前节点没有左孩子,就让左孩子指向父亲,同时让其节点类型变

angry_youth的博客 891

数据结构-二叉树线索化迭代器(续上节)

#pragma once #include using namespace std; enum Type { LINK, //指针指向的是一颗子树 THREAD //指针指向的是线索化 }; template struct BinaryTreeThdNode //二叉树的节点结构 { T _data; BinaryTreeThdNode* _left; BinaryTr

turn__back的博客 371

二叉搜索树的迭代器

我们经常使用着我们并不熟悉的函数/类,我们只知道它们所提供的接口以及怎样使用。这就像我们开车在马路上,你可能并不知道汽车是如何运行,或许你会说这并不需要知道。但至少知道一些回在车抛锚的时候你能做一些事,而不是抽根烟无所事事等维修队过来(如果路上很挤,你就倒霉了)。 我们也有必要知道问题来源在程序出问题的时侯。 //////////////////////////////////////////

fengasdfgh的博客 1596

线索二叉树:从原理到实战应用全解析

本文深入解析了线索二叉树的原理与实战应用。作为一种巧妙利用空指针域的数据结构,线索二叉树通过线索化改造,将遍历序列中的前驱和后继信息存储在闲置指针中,从而实现了无需递归栈的高效中序遍历。文章详细阐述了其结构实现、线索化算法,并探讨了在迭代器设计、快速查找前驱后继等场景下的具体应用,帮助开发者理解如何利用这一数据结构提升程序性能。

web99的专栏 219
上一篇: 【java】写一个公交车类,包含乘客类数组,实现乘客上车下车等方法。
下一篇: 购买阿里云服务器和域名之后需要做的事
pointer_y
博客等级 码龄11年 157粉丝 107原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值