Java中如何构建平衡二叉树

定义:平衡二叉树是一棵二叉排序树,或者为空,或者满足以下条件:

             1)左右子树高度差的绝对值不大于1;

             2)左右子树都是平衡二叉树。

平衡因子:左子树的高度减去右子树的高度,显然,在平衡二叉树中,每个结点的平衡因子的值为-1,0或1。

在Java中,构造平衡二叉树通常涉及到 AVL 树(Adelson-Velsky and Landis tree)的实现。AVL 树是一种自平衡二叉搜索树,它通过保持每个节点的左右子树高度差不超过1来保持平衡。

插入操作的可能情况:

        LL型:新插入结点在A的左孩子(L)的左子树(L)中;

        LR型:新插入结点在A的左孩子(L)的右子树(R)中;

        RL型:新插入结点在A的右孩子(R)的左子树(L)中;

        RR型:新插入结点在A的右孩子(R)的右子树(R)中。

LL型:右旋是指将一个节点的左子树变为其父节点,同时该节点成为其左子树的右子节点。右旋用于解决左子树过深的情况。

LR型:右左旋是先对当前节点的右子树进行右旋,然后再对当前节点进行左旋。这用于解决右子树的左子树过深的情况。

RL型:左右旋是先对当前节点的左子树进行左旋,然后再对当前节点进行右旋。这用于解决左子树的右子树过深的情况。

RR型:左旋是指将一个节点的右子树变为其父节点,同时该节点成为其右子树的左子节点。左旋用于解决右子树过深的情况。

以上都是基于左旋和右旋实现的,那么接下来我们构建左旋和右旋的方法以及插入数据对树结构所做操作:

对一组数据构建平衡二叉树:10、5、20、13、17、4

现在我们利用代码实现。

首先,需要创建一个 TreeNode 类,这个类除了包含节点值之外,还需要保存节点的高度:

public class TreeNode {int val;int height;TreeNode left;TreeNode right;public TreeNode(int val) {this.val = val;this.height = 1; // 初始高度为1}
}

然后,创建一个 AVL 树的实现类,其中包括插入操作和平衡操作:

public class AVLTree {private TreeNode root;// 获取节点的高度private int height(TreeNode node) {if (node == null) {return 0;}return node.height;}// 获取平衡因子private int getBalance(TreeNode node) {if (node == null) {return 0;}return height(node.left) - height(node.right);}// 更新节点的高度private void updateHeight(TreeNode node) {if (node != null) {node.height = Math.max(height(node.left), height(node.right)) + 1;}}// 右旋转private TreeNode rightRotate(TreeNode y) {TreeNode x = y.left;TreeNode T2 = x.right;// 执行旋转x.right = y;y.left = T2;// 更新高度updateHeight(y);updateHeight(x);return x;}// 左旋转private TreeNode leftRotate(TreeNode x) {TreeNode y = x.right;TreeNode T2 = y.left;// 执行旋转y.left = x;x.right = T2;// 更新高度updateHeight(x);updateHeight(y);return y;}// 插入节点public TreeNode insert(TreeNode node, int val) {if (node == null) {return new TreeNode(val);}// 执行标准的BST插入if (val < node.val) {node.left = insert(node.left, val);} else if (val > node.val) {node.right = insert(node.right, val);} else {// 重复的值不被允许return node;}// 更新节点的高度updateHeight(node);// 获取平衡因子int balance = getBalance(node);// 左子树的左侧插入,需要右旋转if (balance > 1 && val < node.left.val) {return rightRotate(node);}// 右子树的右侧插入,需要左旋转if (balance < -1 && val > node.right.val) {return leftRotate(node);}// 左子树的右侧插入,需要先左旋转再右旋转if (balance > 1 && val > node.left.val) {node.left = leftRotate(node.left);return rightRotate(node);}// 右子树的左侧插入,需要先右旋转再左旋转if (balance < -1 && val < node.right.val) {node.right = rightRotate(node.right);return leftRotate(node);}return node;}// 插入新节点,外部调用该方法public TreeNode insert(int val) {root = insert(root, val);//返回根节点return root;}}

定义一个BinaryTreePrinter类,使用深度优先搜索来打印二叉树:

public class BinaryTreePrinter {public static void printTree(TreeNode root) {printTreeHelper(root, 0);}private static void printTreeHelper(TreeNode node, int depth) {if (node == null) {return;}// 打印右子树,使其显示在上方printTreeHelper(node.right, depth + 1);// 打印当前节点for (int i = 0; i < depth; i++) {System.out.print("    "); // 每层缩进四个空格}System.out.println(node.val);// 打印左子树,使其显示在下方printTreeHelper(node.left, depth + 1);}
}

在测试类Test中创建了一个 AVLTree 实例,并调用其方法来操作 AVL 树:

public class Test {public static void main(String[] args) {AVLTree avlTree =new AVLTree();// 构造一棵平衡二叉树      avlTree.insert(5);avlTree.insert(10);avlTree.insert(20);avlTree.insert(13);avlTree.insert(17);TreeNode root=avlTree.insert(12);System.out.println("平衡二叉树高度:"+root.height);BinaryTreePrinter.printTree(root);}
}

根节点为13,结果如下:

与构建结果相同。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

卡码网语言基础课 | 15. 链表的基础操作Ⅲ

目录 一、 插入链表的过程 二、 删除链表的过程 三、 打印链表 3.1 判断节点是否处于链尾 3.2 打印链表 3.3 循环体结束&#xff0c;遍历打印 题目&#xff1a; 请编写一个程序&#xff0c;实现以下链表操作&#xff1a;构建一个单向链表&#xff0c;链表中包含一组整数…

python爱心代码高级

在Python中&#xff0c;我们可以使用matplotlib库来创建一个更高级的爱心图形。以下是一个示例&#xff1a; import matplotlib.pyplot as pltimport numpy as npx np.linspace(-2, 2, 1000)y1 np.sqrt(1-(abs(x)-1)**2)y2 -3*np.sqrt(1-(abs(x)/2)**0.5)fig, ax plt.subp…

uni-app 微信小程序 pdf预览

<div click"getPDF">查看体检报告</div>getPDF() {uni.downloadFile({url: ${this.$baseURL}/file/download?id${this.pdfFileId},//编写在线的pdf地址success: function(res) {const filePath res.tempFilePath;uni.openDocument({filePath: filePath…

随时随地,打开浏览器即可体验的在线PS编辑器

即时设计 即时设计是国产的专业级 UI 设计工具&#xff0c;不限平台不限系统&#xff0c;在浏览器打开即用&#xff0c;能够具备 Photoshop 的设计功能&#xff0c;钢笔、矢量编辑、矩形工具、布尔运算等设计工具一应俱全&#xff0c;是能够在线使用的 Photoshop 免费永久工具…

给csgo搬砖新手的十大建议

1、不要参与赌博性质的开箱和炼金&#xff0c;因为真的会上瘾&#xff0c;赚了还好&#xff0c;亏了你得哭。 2、实在想要玩饰品&#xff0c;直接去悠悠有品或者网易buff看价格&#xff0c;底价再砍10元&#xff0c;总会有人愿意卖的。 3、在steam上不要接受陌生人的好友申请&…

解析d3dcompiler_47.dll缺失怎么修复,4种方法修复d3dcompiler_47.dll文件

d3dcompiler_47.dll缺失怎么修复&#xff1f;其实在我们使用计算机操作的过程中&#xff0c;有时会遇到一些由dll文件错误导致的问题&#xff0c;其中d3dcompiler_47.dll丢失就是这样一种。那么究竟d3dcompiler_47.dll缺失是什么意思&#xff0c;为何它会发生丢失&#xff0c;以…

sqli-labs靶场详解(less1-less10)

目录 less-1 less-2 less 3 less 4 less 5 less-6 less-7 less-8 less-9 less-10 1-10关代码分析 less-1 判断注入点 ?id1 正常 ?id1 报错&#xff1a;to use near 1 ?id1\ 报错&#xff1a;to use near 1\ ?id1 and 11 正常 ?id1 and 11 报错&#xff1a;to …

Snagit 2024.0.1(Mac屏幕截图软件)

Snagit 2024是一款屏幕截图工具&#xff0c;可以帮助用户轻松捕获、编辑和分享屏幕截图。该工具在Mac上运行&#xff0c;旨在满足用户对于屏幕截图的各种需求。 Snagit 2024支持屏幕录制功能&#xff0c;可以录制摄像头和麦克风等外部设备&#xff0c;让用户录制更加全面的视频…

干货分享 | TSMaster采样点配置方法与消除错误帧流程

当通讯节点间采样点参数和波特率参数不匹配造成一些错误帧时&#xff0c;我们如何在TSMaster中设置以及调整波特率参数和采样点参数&#xff0c;来减少以及消除总线上出现的错误帧&#xff0c;进一步提高通信质量。本文着重讲解讲解如何借用TSmaster更加便捷地获取相应的采样点…

js 获取数组的最大值与最小值

let arr [1, 2, 5, 8, 10, 100, -1] 1. 使用Math的静态方法max/min Math.max()函数返回给定的一组数中的最大值。 它的语法&#xff1a;Math.max(value1[, value2, ...]) 使用此方法&#xff0c;需要注意&#xff0c;如果没有参数的话&#xff0c;则返回-Infinity。如果有任一…

前端学习系列之html

目录 初识html 发展史 优势 W3C 标准 地址 格式 网页基本标签 标题标签 段落标签 换行标签 水平线标签 字体样式 注释和特殊符号 特殊符号 图像、超链接 图像 常见图像格式 格式 超链接 格式 重要属性 href&#xff1a;规定链接指向的页面的 URL target…

拼多多Temu销量大涨,三个月销量冲上热搜,Temu狂飙既要又要合规性证书

电商巨头拼多多野心之大&#xff0c;大到国内市场装不下。于是乎&#xff0c;跨境业务Temu于2022年下半年在美国上线2023年随着销量的不断狂飙&#xff0c;Temu平台对质量也是提出了卖家证明产品质量过关的合规性证书&#xff01; Temu在 8月的单日GMV达5000万美金&#xff0c…