十、顺序存储二叉树、线索化二叉树

news2024/12/23 13:45:55

1、二叉树顺序存储

1.1 特点

  • 顺序二叉树通常只考虑完全二叉树
  • 第n个元素的左子节点为2*n+1
  • 第n个元素的右子节点为2*n+2
  • 第n个元素的父节点为(n-1)/2
    n:表示二叉树中的第几个元素(按0开始编号),也可以理解为n为数组下标。
    在这里插入图片描述

1.2、基本说明

从数据存储来看,数组存储方式和树的存储方式可以相互转换,即数组可以转换成树,树也可以转换成数组。

1.3、案例

上图二叉树的节点,要求以数组的方式来存放arr:[1,2,3,4,5,6,7],在遍历数组时,以前序、中序、后序遍历的方式完成节点的遍历。

public class ArrBinaryTreeDemo {

	public static void main(String[] args) {
		int[] arr = {1,2,3,4,5,6,7};
		ArrBinaryTree arrBinaryTree = new ArrBinaryTree(arr);
		//arrBinaryTree.preOrder(0);
		//arrBinaryTree.infixOrder(0);
		arrBinaryTree.postOrder(0);
	}

}

class ArrBinaryTree{
	private int[] arr;

	public ArrBinaryTree(int[] arr) {
		this.arr = arr;
	}

	/**
	 * 前序遍历:1 2 4 5 3 6 7
	 * @param index
	 */
	public void preOrder(int index) {
		if (arr == null || arr.length == 0) {
			System.err.println("数组为空,不能进行二叉树遍历");
			return;
		}
		//输出当前元素
		System.out.println(arr[index]);
		//向左递归遍历
		if ((index * 2 + 1) < arr.length) {
			preOrder(index * 2 + 1);
		}
		//向右递归遍历
		if ((index * 2 + 2) < arr.length) {
			preOrder(index * 2 + 2);
		}
	}

	/**
	 * 中序遍历:2 4 5 1 3 6 7 
	 * @param index
	 */
	public void infixOrder(int index) {
		if (arr == null || arr.length == 0) {
			System.err.println("数组为空,不能进行二叉树遍历");
			return;
		}
		//向左递归遍历
		if ((index * 2 + 1) < arr.length) {
			infixOrder(index * 2 + 1);
		}
		//输出当前元素
		System.out.println(arr[index]);
		//向右递归遍历
		if ((index * 2 + 2) < arr.length) {
			infixOrder(index * 2 + 2);
		}
	}

	/**
	 * 后序遍历:2 4 5 3 6 7 1
	 * @param index
	 */
	public void postOrder(int index) {
		if (arr == null || arr.length == 0) {
			System.err.println("数组为空,不能进行二叉树遍历");
			return;
		}
		//向左递归遍历
		if ((index * 2 + 1) < arr.length) {
			postOrder(index * 2 + 1);
		}
		//向右递归遍历
		if ((index * 2 + 2) < arr.length) {
			postOrder(index * 2 + 2);
		}
		//输出当前元素
		System.out.println(arr[index]);
	}
}

2、线索化二叉树

2.1 问题

将数列{1,3,6,8,10,14}构建成一颗二叉树
在这里插入图片描述
问题分析:

  • 当我们对上面的二叉树进行中序遍历时,数列为{8,3,10,1,14,6}
  • 但是6,8,10,14这几个节点的左右指针,并没有完全的利用上
  • 如果我们希望充分的利用各个节点的左右指针,让各个节点可以指向自己的前后节点,怎么办?
  • 解决方案就是线索化二叉树

2.2 基本介绍

  • n个节点的二叉链表中含有n+1个空指针域。利用二叉链表中的空指针域,存放指向该节点在某种遍历次序下的前驱和后继节点的指针(这种附加的指针称为线索)
  • 这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(Threaded BinaryTree)。根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种。
  • 一个节点的前一个节点,称为前驱节点
  • 一个节点的后一个节点,称为后继节点

2.3 应用案例

将上图的二叉树进行中序线索二叉树,中序遍历的数列为{8,3,10,1,14,6}
在这里插入图片描述

2.4 代码实现

public class ThreadedBinaryTreeDemo {

	public static void main(String[] args) {
		// 测试中序线索二叉树
		HeroNode root = new HeroNode(1, "tom");
		HeroNode node2 = new HeroNode(3, "jack");
		HeroNode node3 = new HeroNode(6, "smith");
		HeroNode node4 = new HeroNode(8, "mary");
		HeroNode node5 = new HeroNode(10, "king");
		HeroNode node6 = new HeroNode(14, "dim");

		// 二叉树
		root.setLeft(node2);
		root.setRight(node3);
		node2.setLeft(node4);
		node2.setRight(node5);
		node3.setLeft(node6);

		ThreadedBinaryTree threadedBinaryTree = new ThreadedBinaryTree();
		threadedBinaryTree.setRoot(root);
		HeroNode leftNode = node5.getLeft();
		HeroNode rightNode = node5.getRight();
		System.out.println("线索化前:10号结点的前驱结点为:" + leftNode);// 3
		System.out.println("线索化前:10号结点的后继结点为:" + rightNode);// 1
		threadedBinaryTree.threadedNodes(root);

		// 测试,以10号结点测试
		leftNode = node5.getLeft();
		rightNode = node5.getRight();
		System.out.println("10号结点的前驱结点为:" + leftNode);// 3
		System.out.println("10号结点的后继结点为:" + rightNode);// 1
	}

}

//定义线索化二叉树
class ThreadedBinaryTree {
	private HeroNode root;
	private HeroNode pre = null;

	public void setRoot(HeroNode root) {
		this.root = root;
	}

	/**
	 * 编写对二叉树进行中序线索化的方法
	 * 
	 * @param node 当前需要线索化的节点
	 */
	public void threadedNodes(HeroNode node) {
		if (node == null) {
			return;
		}
		// 线索化左子树
		threadedNodes(node.getLeft());

		// 线索化当前节点
		// 处理当前节点的前驱节点
		if (node.getLeft() == null) {
			node.setLeft(pre);
			node.setLeftType(1);
		}
		// 处理当前节点的后继节点
		if (pre != null && pre.getRight() == null) {
			pre.setRight(node);
			pre.setRightType(1);
		}
		// 每次处理一个节点后,让当前节点是下一个节点的前驱节点
		pre = node;

		// 线索化右子树
		threadedNodes(node.getRight());

	}
}

class HeroNode {
	private int no;
	private String name;
	private HeroNode left;
	private HeroNode right;

	// 说明
	// 1.如果leftType==0 表示指向的是左子树,为1 表示指向前驱节点
	// 2.如果rightType==0 表示指向的是右子树,为1 表示指向后继节点
	private int leftType;
	private int rightType;

	public int getLeftType() {
		return leftType;
	}

	public void setLeftType(int leftType) {
		this.leftType = leftType;
	}

	public int getRightType() {
		return rightType;
	}

	public void setRightType(int rightType) {
		this.rightType = rightType;
	}

	public HeroNode(int no, String name) {
		super();
		this.no = no;
		this.name = name;
	}

	public int getNo() {
		return no;
	}

	public void setNo(int no) {
		this.no = no;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public HeroNode getLeft() {
		return left;
	}

	public void setLeft(HeroNode left) {
		this.left = left;
	}

	public HeroNode getRight() {
		return right;
	}

	public void setRight(HeroNode right) {
		this.right = right;
	}

	@Override
	public String toString() {
		return "HeroNode [no=" + no + ", name=" + name + "]";
	}

}

输出结果:
在这里插入图片描述

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

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

相关文章

力扣刷题记录——804. 唯一摩尔斯密码词、806. 写字符串需要的行数、824. 山羊拉丁文

本专栏主要记录力扣的刷题记录&#xff0c;备战蓝桥杯&#xff0c;供复盘和优化算法使用&#xff0c;也希望给大家带来帮助&#xff0c;博主是算法小白&#xff0c;希望各位大佬不要见笑&#xff0c;今天要分享的是——《力扣刷题记录——804. 唯一摩尔斯密码词、806. 写字符串…

Apache两个解析漏洞复现及防御方法

一、多后缀解析漏洞 形成原因&#xff1a; 配置apache时&#xff0c;对于apache配置不熟练&#xff0c;配置命令不清楚&#xff0c;在配置PHP文件处理程序时&#xff0c;配置命令存在问题&#xff1a;位于漏洞环境目录的 conf/docker-php.conf里的配置命令&#xff08;AddHand…

路由策略实验(华为)

题目&#xff1a; 思路&#xff1a; 为完成实验达成目的&#xff0c;需要明确两个区域内的协议&#xff0c;并且要避免造成环路&#xff0c;故需要改变r3-r1,r3-r4两边的优先级&#xff0c;可以避免造成环路&#xff0c;并且需要达到选路最优&#xff0c;设置匹配规则&#xff…

【机器学习】逻辑回归(实战)

逻辑回归&#xff08;实战&#xff09; 目录一、准备工作&#xff08;设置 jupyter notebook 中的字体大小样式等&#xff09;二、绘制 sigmoid 函数&#xff1a;σ(z)11e−z\sigma(z)\frac{1}{1e^{-z}}σ(z)1e−z1​三、查看鸢尾花数据集1、加载 iris 数据集并查看2、设计二分…

[Java]Maven学习笔记(尚硅谷2022)

文章目录&#x1f97d; Maven概述&#x1f30a; Maven的功能&#x1f30a; Maven简介&#x1f4a6; 构建&#x1f4a6; 依赖&#x1f4a6; Maven 的工作机制&#x1f97d; Maven核心程序解压和配置&#x1f30a; Maven 核心程序解压与配置&#x1f4a6; 下载&#x1f4a6; 解压…

电脑本地安装不同版本MySQL

本地已经安装了mysql5.7版本&#xff0c;想测试mysql8版本的用法&#xff0c;想在一台电脑同时配置不同版本的mysql在不同端口号&#xff0c;看起来简单&#xff0c;实现起来其实挺多坑的&#xff0c;总结下实战经验和大家分享下 一、下载安装 下载地址 二、配置 1、解压缩…

word标签功能:如何快速制作批量产品贴纸标签

在日常生活中&#xff0c;在商店购物时&#xff0c;经常可以看到&#xff0c;商品架上放有产品贴纸标签&#xff0c;用于消费者识别产品价格、日期或者组合成分等。在日常办公中&#xff0c;在办公用品或仓库物料上&#xff0c;同样也能看到贴纸标签&#xff0c;用于物品的分类…

Go语言安装

1. 介绍 Go语言是一门编译型语言。Go的语法接近C语言&#xff0c;但对于变量的声明有所不同。Go支持垃圾回收功能。 C/C&#xff1a;C/C语言直接编译成机器码&#xff0c;不需要执行环境&#xff0c;直接执行在操作系统上&#xff1b; Java&#xff1a;Java会先编译成字节码.c…

es6对象中的简写形式

对象属性简写 let name ww; let age 18; // es5写法 let es5 {name: name,age: age, }; // es6写法 let es6 {name,age }函数简写 let obj {es5: function () {}, // es5写法es6() {} // es6写法&#xff0c;省略 :function }计算属性名 let name ww; let age 18 let o…

前后端鉴权的10种方案

文章目录0、基本概念认证授权鉴权权限控制认证、授权、鉴权和权限控制的关系1. HTTP 基本鉴权1.1 认证流程图1.2 认证步骤解析1.2 认证步骤解析1.3 优点1.4 缺点1.5 使用场景2. Session-Cookie 鉴权2.1 什么是 Cookie2.2 什么是 Session2.3 Session-Cookie 的认证流程图2.4 Ses…

一起Talk Android吧(第四百七十八回:旋转类视图动画)

文章目录使用方法属性介绍示例代码各位看官们大家好&#xff0c;上一回中咱们说的例子是"平移类视图动画",这一回中咱们说的例子是"旋转类视图动画"。闲话休提&#xff0c;言归正转&#xff0c;让我们一起Talk Android吧&#xff01; 使用方法 旋转类动画…

【Java项目】从0到1构建一个博客系统

✨哈喽&#xff0c;进来的小伙伴们&#xff0c;你们好耶&#xff01;✨ &#x1f6f0;️&#x1f6f0;️系列专栏:【JavaWeb】 ✈️✈️本篇内容:从0到1构建一个博客系统&#xff01; &#x1f680;&#x1f680;代码托管平台github&#xff1a;博客系统源码托管&#xff01; ⛵…

【Git】自建代码托管平台-GitLab

10.1、GitLab 简介 GitLab 是由 GitLabInc.开发&#xff0c;使用 MIT 许可证的基于网络的 Git 仓库管理工具&#xff0c;且具有wiki 和 issue 跟踪功能。使用 Git 作为代码管理工具&#xff0c;并在此基础上搭建起来的 web 服务。 GitLab 由乌克兰程序员 DmitriyZaporozhets …

数据分析-深度学习Pytorch Day11

首先要搞懂损失函数与代价函数。损失函数是单个样本与真实值之间的差距代价函数是整个样本集与真实值的平均差距随机梯度下降就是不使用代价函数对参数进行更新&#xff0c;而是使用损失函数对参数更新。梯度下降法( gradient descent )是一阶最优化算法&#xff0c;通常也称为…

SpringBoot+VUE前后端分离项目学习笔记 - 【27 SpringBoot集成Redis】

以首页的文件访问作为示例使用Redis 一方面加快用户访问速度 一方面缓解频繁访问数据库的压力 之前每次访问首页都会请求数据库数据 Redis安装以及配置 所需文件 解压后&#xff0c;双击下述脚本&#xff0c;启动redis 可视化软件安装、设置安装路径然后一直点下一步就OK …

Java OpenJDK 8u362 Windows x64 Installer

文章目录&#xff08;一&#xff09;Azul&#xff08;二&#xff09;Adopt&#xff08;三&#xff09;IBM&#xff08;四&#xff09;Oracle&#xff08;一&#xff09;Azul WEB Page&#xff1a;&#x1f517;Download Azul Zulu Builds of OpenJDK Windows installer&#xf…

一位老测试对测试用例之个人见解

刚入行的时候&#xff0c;看了很多关于测试相关的文章&#xff0c;记得有一篇说到测试用例是测试灵魂让我印象深刻。如今&#xff0c;我入行几年了&#xff0c;越发深感测试用例的设计重要性&#xff0c;可以这么说&#xff0c;测试用例的设计与管理是测试工程师的核心技能。我…

一套计算机网络系统设计方案,包含外网、内网、智能化设备网

一套计算机网络系统设计方案&#xff0c;包含外网、内网、智能化设备网。 弱电工程设计的计算机网络系统一般分为三种&#xff1a;内网、外网、设备网&#xff0c;这三种网络系统如何设计&#xff1f;它们的架构是如何的呢&#xff1f; 计算机网络系统就是利用通信设备和线路将…

面试_Http常见问题

http协议的默认端口 80 应用层有哪些协议 http ,FTP,SMTP,DNS,MQ 在浏览器中输入网址后会发生什么&#xff1a; 首先服务器有自己的ip地址&#xff0c;但ip地址对人来说很难记&#xff0c;所以人会在浏览器里输入域名&#xff0c;然后经过DNS解析为ip,访问对应的服务器 与服务…

内网云盘如何内网穿透实现公网访问

云盘是一种专业的互联网存储工具&#xff0c;是互联网的云技术产物&#xff0c;它通过互联网为企业和个人提供信息的存储、读取、下载等服务&#xff0c;具有安全稳定、海量存储的特点。随着企业信息化发展&#xff0c;云盘系统需求不断扩大&#xff0c;相关系统软件被广泛应用…