树结构及其算法-线索二叉树

news2024/11/27 12:33:33

目录

树结构及其算法-线索二叉树

C++代码


树结构及其算法-线索二叉树

虽然我们把树转换为二叉树可减少空间的浪费——由2/3降低到1/2,但是如果仔细观察之前使用链表建立的n节点二叉树,那么会发现用来指向左右两个节点的指针只有n-1个链接,另外的n+1个指针都是空链接。

所谓线索二叉树(Threaded Binary Tree),就是把这些空链接加以利用,再指到树的其他节点,这些链接就称为线索(Thread),而这棵树就称为线索二叉树。将二叉树转换为线索二叉树的步骤如下:

  1. 先将二叉树通过中序遍历方式按序排出,并将所有空链接改成线索。
  2. 如果线索链接指向该节点的左链接,就将该线索指向中序遍历顺序下的前一个节点。
  3. 如果线索链接指向该节点的右链接,就将该线索指向中序遍历顺序下的后一个节点。
  4. 指向一个空节点,并将此空节点的右链接指向自己,而空节点的左子树是此线索二叉树。

线索二叉树的基本结构如下:

  • LBIT:左控制位
  • LCHILD:左子树链接
  • DATA:节点数据
  • RCHILD:右子树链接
  • RBIT:右控制位

和链表所建立的二叉树不同之处在于。为了区别正常指针或线索而加入的两个字段:LBIT和RBIT。

  • 若LCHILD为正常指针,则LBIT=1。
  • 若LCHILD为线索,则LBIT=0。
  • 若RCHILD为正常指针,则RBIT=1。
  • 若RCHILD为线索,则RBIT=0。

节点的声明方式如下:

struct TreeNode {
	int data;
	int leftThread;
	int rightThread;
	TreeNode* leftNode;
	TreeNode* rightNode;
};

以下是使用线索二叉树的优缺点:

优点:

  1. 在二叉树中进行中序遍历时,不需要使用堆栈处理,但一般二叉树需要。
  2. 由于充分使用了空链接,因此避免了链接闲置浪费的情况。另外,在中序遍历时速度较快,节省不少时间。
  3. 任一节点都容易找出它的中序先行者与中序后继者,在中序遍历时可以不使用堆栈或递归。

缺点:

  1. 在加入或删除节点时的速度比一般二叉树慢。
  2. 线索子树间不能共用。

C++代码

#include<iostream>
using namespace std;

struct TreeNode {
	int data;
	int leftThread;
	int rightThread;
	TreeNode* leftNode;
	TreeNode* rightNode;
	TreeNode() {
		data = 0;
		leftThread = 0;
		rightThread = 0;
		leftNode = nullptr;
		rightNode = nullptr;
	}
	TreeNode(int tempData, int tempLeftThread = 0, int tempRightThread = 0, TreeNode* tempLeftNode = nullptr, TreeNode* tempRightNode = nullptr) {
		this->data = tempData;
		this->leftThread = tempLeftThread;
		this->rightThread = tempRightThread;
		this->leftNode = tempLeftNode;
		this->rightNode = tempRightNode;
	}
};

namespace Tree {
	TreeNode* CreateTree(int* tempData, int tempSize) {
		TreeNode* root = nullptr;
		for (int i = 0; i < tempSize; i++) {
			TreeNode* newTreeNode = new TreeNode(tempData[i]);
			TreeNode* previousTreeNode = new TreeNode(tempData[i]);
			TreeNode* currentTreeNode = new TreeNode();
			TreeNode* parentTreeNode = new TreeNode();
			int pos;
			if (root == nullptr) {
				root = newTreeNode;
				root->leftNode = root;
				root->rightThread = 1;
				continue;
			}
			currentTreeNode = root->rightNode;
			if (currentTreeNode == nullptr) {
				root->rightNode = newTreeNode;
				newTreeNode->leftNode = root;
				newTreeNode->rightNode = root;
				continue;
			}
			parentTreeNode = root;
			pos = 0;
			while (currentTreeNode != nullptr) {
				if (currentTreeNode->data > tempData[i]) {
					if (pos != -1) {
						pos = -1;
						previousTreeNode = parentTreeNode;
					}
					parentTreeNode = currentTreeNode;
					if (currentTreeNode->leftThread == 1)
						currentTreeNode = currentTreeNode->leftNode;
					else
						currentTreeNode = nullptr;
				}
				else {
					if (pos != 1) {
						pos = 1;
						previousTreeNode = parentTreeNode;
					}
					parentTreeNode = currentTreeNode;
					if (currentTreeNode->rightThread == 1)
						currentTreeNode = currentTreeNode->rightNode;
					else
						currentTreeNode = nullptr;
				}
			}
			if (parentTreeNode->data > tempData[i]) {
				parentTreeNode->leftThread = 1;
				parentTreeNode->leftNode = newTreeNode;
				newTreeNode->leftNode = previousTreeNode;
				newTreeNode->rightNode = parentTreeNode;
			}
			else {
				parentTreeNode->rightThread = 1;
				parentTreeNode->rightNode = newTreeNode;
				newTreeNode->rightNode = previousTreeNode;
				newTreeNode->leftNode = parentTreeNode;
			}
		}
		return root;
	}
	void Inorder(TreeNode* root) {
		TreeNode* tempTreeNode = root;
		do {
			if (tempTreeNode->rightThread == 0)
				tempTreeNode = tempTreeNode->rightNode;
			else {
				tempTreeNode = tempTreeNode->rightNode;
				while (tempTreeNode->leftThread != 0)
					tempTreeNode = tempTreeNode->leftNode;
			}
			if (tempTreeNode != root)
				cout << tempTreeNode->data << " ";
		} while (tempTreeNode != root);
		cout << endl;
	}
};

int main() {
	int data[]{ 0, 6, 3, 5, 9, 7, 8, 4, 2 };
	cout << "原始数据:" << endl;
	for (int i = 1; i < 9; i++)
		cout << data[i] << " ";
	cout << endl;

	TreeNode* treeNode = Tree::CreateTree(data,9);
	cout << "排序结果:" << endl;
	Tree::Inorder(treeNode);
	return 0;
}

输出结果

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

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

相关文章

如何快速导出、备份微信通讯录好友联系人微信号

6-9 如果因工作需要&#xff0c;你有多个微信&#xff0c;并且你的业务开发的客户都在这些微信里&#xff0c;将会面临一个问题&#xff0c;那就是备份问题&#xff0c;因为通过微信做业务&#xff0c;如果遇到微信不小心被封号&#xff0c;或者离职的交接等情况&#xff0c;客…

【Mybatis小白从0到90%精讲】03:编写Mapper,第一个入门程序

文章目录 前言一、创建mysql user表二、注解方式三、XML方式四、编写main方法调用前言 映射器Mapper是 MyBatis 中最重要的文件,简单的讲主要用来映射SQL语句。 映射器有两种实现方式:注解方式、XML文件方式(推荐)。 接下来演示通过两种方式,开发Mybatis第一个入门程序,…

GEE数据集——2019、2020、2021、2022和2023年全球固定宽带和移动(蜂窝)网络性能Shapefile 格式数据集

全球固定宽带和移动&#xff08;蜂窝&#xff09;网络性能 全球固定宽带和移动&#xff08;蜂窝&#xff09;网络性能&#xff0c;分配给缩放级别 16 网络墨卡托图块&#xff08;赤道处约 610.8 米 x 610.8 米&#xff09;。数据以 Shapefile 格式和 Apache Parquet 格式提供&…

安装MySQL时出现 由于找不到 MSVCR120.dll,无法继续执行代码。重新安装程序可能会解决此问题。

--------------------------- mysqld.exe - 系统错误 --------------------------- 由于找不到 MSVCR120.dll&#xff0c;无法继续执行代码。重新安装程序可能会解决此问题。 --------------------------- 确定 --------------------------- 安装MySQL时出现 “This appl…

C语言实现九九乘法表

学习C语言后&#xff0c;我们会发现打印九九乘法表是很简单的&#xff0c;话不多说&#xff0c;我们上代码&#xff01; 目录 1.函数代码 2.运行结果 1.函数代码 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() {int i 1;int j 1;int n 0;//行数in…

麒麟系统 UFW 操作文档

麒麟系统 UFW 操作文档 1. UFW 介绍 ufw&#xff08;简单防火墙 Uncomplicated FireWall&#xff09;真正地简化了 iptables&#xff0c;虽然 ufw 的底层依 然会调用 iptables&#xff0c;但是配置防火墙规则时操作更加方便&#xff0c;命令更加简洁&#xff0c;本文档主要介…

49基于matlab的Non dominated sorting genetic algorithm -II(NSGA-Ⅱ)多目标遗传算法

基于matlab的Non dominated sorting genetic algorithm -II&#xff08;NSGA-Ⅱ&#xff09;多目标遗传算法&#xff0c;其优势是降低了非劣排序遗传算法的复杂性&#xff0c;具有运行速度快&#xff0c;解集的收敛性好的优点&#xff0c;成为其他多目标优化算法性能的基准。程…

Python自定义函数练习(持续更新中~)

1.计算矩阵的面积和周长&#xff1a; class Rectangle:def __init__(self, width, height):self.width widthself.height heightdef area(self):return self.width * self.heightdef perimeter(self):return 2 * (self.width self.height)if __name__ "__main__"…

Ubuntu网络IP地址一直显示127.0.0.1

问题描述&#xff1a; 终端输入ip a显示127.0.0.1&#xff0c;原来类似192.168.231.1的地址不见了。 ip a 点击网络配置&#xff08;ubuntu桌面版&#xff09;&#xff0c;发现无线网络模块看不见了 正常情况应该有wired 模块&#xff0c;就是下面标红的 解决方案&#xff1a…

c语言实现http下载功能,显示进度条和下载速率

#include <stdio.h>//printf #include <string.h>//字符串处理 #include <sys/socket.h>//套接字 #include <arpa/inet.h>//ip地址处理 #include <fcntl.h>//open系统调用 #include <unistd.h>//write系统调用 #include <netdb.h>//…

时序分解 | Matlab实现PSO-VMD粒子群算法优化变分模态分解时间序列信号分解

时序分解 | Matlab实现PSO-VMD粒子群算法优化变分模态分解时间序列信号分解 目录 时序分解 | Matlab实现PSO-VMD粒子群算法优化变分模态分解时间序列信号分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 PSO-VMD粒子群算法PSO优化VMD变分模态分解 可直接运行 分解效果…

Linux C/C++下抓包分析mysql流量(协议解析)

MySQL通信协议是一个有状态的协议&#xff0c;主要用于MySQL客户端与服务器之间的通信。这个协议在MySQL客户端连接器&#xff08;如Connector/C、Connector/J等&#xff09;、MySQL Proxy以及主从复制中都有实现。 该协议的特性包括&#xff1a;支持SSL、压缩和认证等功能。 …

【JavaScript】零碎知识点总结_2

1. 引入网站图标 可以直接放在根目录 还可以 link 引入&#xff08;推荐&#xff09; <linkrel"shortcut icon"href"./assets/favicon.ico"type"image/x-icon">2. 转换为数字 123 -> 123 除 做字符串拼接&#xff0c;算术运算符都…

梳理自动驾驶中的各类坐标系

目录 自动驾驶中的坐标系定义 关于坐标系的定义 几大常用坐标系 世界坐标系 自车坐标系 传感器坐标系 激光雷达坐标系 相机坐标系 如何理解坐标转换 机器人基础中的坐标转换概念 左乘右乘的概念 对左乘右乘的理解 再谈自动驾驶中的坐标转换 本节参考文献 自动驾驶…

map和set的例题

随机链表的复制 138. 随机链表的复制 - 力扣&#xff08;LeetCode&#xff09; 我们为什么要拷贝原链表的结点一个个链接到原链表结点的后面&#xff1f; 其实就建立了原链表结点与拷贝链表每个结点的一种映射关系, 方便我们设置拷贝结点的random域。 那我们现在C有了map: …

WPF中的Binding的常见知识点与技巧

完全来源于十月的寒流&#xff0c;感谢大佬讲解 在XAML中&#xff0c;可以绑定到许多不同类型的数据源和属性。以下是一些可以绑定的常见数据源和属性&#xff1a; 属性&#xff1a;可以绑定到对象的属性&#xff0c;例如控件的Text、Visibility、IsEnabled等属性。 集合&am…

爱上C语言:函数递归,青蛙跳台阶图文详解

&#x1f680; 作者&#xff1a;阿辉不一般 &#x1f680; 你说呢&#xff1a;生活本来沉闷&#xff0c;但跑起来就有风 &#x1f680; 专栏&#xff1a;爱上C语言 &#x1f680;作图工具&#xff1a;draw.io(免费开源的作图网站) 如果觉得文章对你有帮助的话&#xff0c;还请…

Python基础入门例程42-NP42 公式计算器(运算符)

最近的博文&#xff1a; Python基础入门例程41-NP41 二进制位运算&#xff08;运算符&#xff09;-CSDN博客 Python基础入门例程40-NP40 俱乐部的成员&#xff08;运算符&#xff09;-CSDN博客 Python基础入门例程39-NP39 字符串之间的比较&#xff08;运算符&#xff09;-C…

Zeus IoT : 基于 SpringBoot 的分布式开源物联网大数据平台

Zeus IoT 是一个集设备数据采集、存储、分析、观测为一体的开源物联网平台&#xff0c;全球首创基于 Zabbix 的物联网分布式数据采集架构&#xff0c;具备超百万级物联网设备的并发监控能力&#xff0c;真正具备工业级性能与稳定性的开源物联网大数据中台。 Zeus IoT 致力于让设…

apachesolr中简单使用

core使用 首先点击add core 可以看到报错solrconfig.xml不在new_core目录下&#xff0c;new_core是我们点击后自动创建的 那么我们将D:\solr2\solr-9.3.0\solr-9.3.0\server\solr\configsets下的任何一个目录下的conf拷贝到new_core过去 这里是使用_default下的conf目录拷贝…