数据结构第10节:平衡树

平衡树是一种特殊的二叉搜索树,它的设计目的是为了保持树的平衡,从而保证所有操作的时间复杂度保持在O(log n),即使在最坏的情况下也是如此。最常见的平衡树之一是AVL树,它是以发明者G.M. Adelson-Velsky和E.M. Landis的名字命名的。

在AVL树中,任何节点的两个子树的高度最大差别不超过1。这意味着AVL树总是尽可能地保持平衡,从而优化了搜索、插入和删除操作的效率。

AVL树的关键概念:

  1. 平衡因子:一个节点的平衡因子是其右子树的高度减去其左子树的高度。平衡因子可以是-1、0或1。

  2. 旋转:当插入或删除操作破坏了树的平衡时,AVL树会执行一系列的旋转操作来重新平衡树。旋转分为以下几种:

    • 单旋转:右旋(Right Rotation)和左旋(Left Rotation)。
    • 双旋转:右旋后再左旋(Right-Left Rotation)或左旋后再右旋(Left-Right Rotation)。

Java实现案例:

我们可以通过下面的Java代码来实现一个基本的AVL树:

public class AVLTree<T extends Comparable<T>> {private Node<T> root;private static class Node<T> {T data;Node<T> left, right;int height;Node(T data) {this.data = data;height = 1;}}private int height(Node<T> N) {if (N == null)return 0;return N.height;}private int getBalance(Node<T> N) {if (N == null)return 0;return height(N.right) - height(N.left);}private Node<T> rightRotate(Node<T> y) {Node<T> x = y.left;Node<T> T2 = x.right;x.right = y;y.left = T2;y.height = Math.max(height(y.left), height(y.right)) + 1;x.height = Math.max(height(x.left), height(x.right)) + 1;return x;}private Node<T> leftRotate(Node<T> x) {Node<T> y = x.right;Node<T> T2 = y.left;y.left = x;x.right = T2;x.height = Math.max(height(x.left), height(x.right)) + 1;y.height = Math.max(height(y.left), height(y.right)) + 1;return y;}private Node<T> insert(Node<T> node, T key) {if (node == null)return new Node<>(key);if (key.compareTo(node.data) < 0)node.left = insert(node.left, key);else if (key.compareTo(node.data) > 0)node.right = insert(node.right, key);elsereturn node;node.height = 1 + Math.max(height(node.left), height(node.right));int balance = getBalance(node);// Left Left Caseif (balance > 1 && key.compareTo(node.left.data) < 0)return rightRotate(node);// Right Right Caseif (balance < -1 && key.compareTo(node.right.data) > 0)return leftRotate(node);// Left Right Caseif (balance > 1 && key.compareTo(node.left.data) > 0) {node.left = leftRotate(node.left);return rightRotate(node);}// Right Left Caseif (balance < -1 && key.compareTo(node.right.data) < 0) {node.right = rightRotate(node.right);return leftRotate(node);}return node;}public void insert(T key) {root = insert(root, key);}// ... 其他方法如删除、查找、遍历等
}

应用案例:

假设我们要构建一个AVL树来存储一组整数,并保持树的平衡状态。我们可以这样使用:

public class Main {public static void main(String[] args) {AVLTree<Integer> avlTree = new AVLTree<>();avlTree.insert(10);avlTree.insert(20);avlTree.insert(30);avlTree.insert(40);avlTree.insert(50);avlTree.insert(25);// 在此之后,avlTree应该是一个平衡的AVL树}
}

以上代码展示了如何使用AVL树插入一些整数值,并自动调整树的平衡。在实际应用中,AVL树可以用于各种需要高效搜索、插入和删除操作的场景,比如数据库索引、符号表等。

下面,我将补充AVL树的删除、查找以及遍历方法。

删除操作

删除操作在AVL树中比较复杂,因为它涉及到保持树的平衡。在删除节点后,需要检查并修复可能的不平衡。

private Node<T> delete(Node<T> root, T key) {if (root == null)return root;if (key.compareTo(root.data) < 0)root.left = delete(root.left, key);else if (key.compareTo(root.data) > 0)root.right = delete(root.right, key);else {if (root.left == null)return root.right;else if (root.right == null)return root.left;root.data = minValue(root.right);root.right = delete(root.right, root.data);}root.height = Math.max(height(root.left), height(root.right)) + 1;int balance = getBalance(root);if (balance > 1 && getBalance(root.left) >= 0)return rightRotate(root);if (balance < -1 && getBalance(root.right) <= 0)return leftRotate(root);if (balance > 1 && getBalance(root.left) < 0) {root.left = leftRotate(root.left);return rightRotate(root);}if (balance < -1 && getBalance(root.right) > 0) {root.right = rightRotate(root.right);return leftRotate(root);}return root;
}private T minValue(Node<T> node) {T minv = node.data;while (node.left != null) {minv = node.left.data;node = node.left;}return minv;
}

查找操作

查找操作在AVL树中相对简单,遵循二叉搜索树的查找规则。

public boolean contains(T key) {return search(root, key) != null;
}private Node<T> search(Node<T> node, T key) {if (node == null || key.equals(node.data))return node;if (key.compareTo(node.data) < 0)return search(node.left, key);elsereturn search(node.right, key);
}

遍历操作

遍历操作包括前序遍历、中序遍历和后序遍历,这里展示中序遍历。

public void inorderTraversal() {inorder(root);
}private void inorder(Node<T> node) {if (node != null) {inorder(node.left);System.out.print(node.data + " ");inorder(node.right);}
}

主方法使用示例

将上述代码整合进AVLTree类中,然后在main方法中使用:

public class Main {public static void main(String[] args) {AVLTree<Integer> avlTree = new AVLTree<>();avlTree.insert(10);avlTree.insert(20);avlTree.insert(30);avlTree.insert(40);avlTree.insert(50);avlTree.insert(25);System.out.println("Inorder traversal of the constructed AVL tree is");avlTree.inorderTraversal();System.out.println();System.out.println("Deleting key 40");avlTree.delete(40);System.out.println("Inorder traversal after deletion is");avlTree.inorderTraversal();System.out.println();System.out.println("Searching for key 25: " + avlTree.contains(25));System.out.println("Searching for key 60: " + avlTree.contains(60));}
}

这段代码演示了如何插入元素、遍历AVL树、删除元素以及查找元素。

以下是前序遍历和后序遍历的代码实现,我们将它们添加到之前的AVLTree类中:

前序遍历

前序遍历的顺序是:根节点 -> 左子树 -> 右子树。

public void preorderTraversal() {preorder(root);
}private void preorder(Node<T> node) {if (node != null) {System.out.print(node.data + " ");preorder(node.left);preorder(node.right);}
}

后序遍历

后序遍历的顺序是:左子树 -> 右子树 -> 根节点。

public void postorderTraversal() {postorder(root);
}private void postorder(Node<T> node) {if (node != null) {postorder(node.left);postorder(node.right);System.out.print(node.data + " ");}
}

更新主方法示例

我们更新main方法来演示这些遍历方法:

public class Main {public static void main(String[] args) {AVLTree<Integer> avlTree = new AVLTree<>();avlTree.insert(10);avlTree.insert(20);avlTree.insert(30);avlTree.insert(40);avlTree.insert(50);avlTree.insert(25);System.out.println("Inorder traversal of the constructed AVL tree is");avlTree.inorderTraversal();System.out.println();System.out.println("Preorder traversal of the constructed AVL tree is");avlTree.preorderTraversal();System.out.println();System.out.println("Postorder traversal of the constructed AVL tree is");avlTree.postorderTraversal();System.out.println();System.out.println("Deleting key 40");avlTree.delete(40);System.out.println("Inorder traversal after deletion is");avlTree.inorderTraversal();System.out.println();System.out.println("Searching for key 25: " + avlTree.contains(25));System.out.println("Searching for key 60: " + avlTree.contains(60));}
}

这段代码展示了如何使用AVL树的各种遍历方法,包括中序遍历、前序遍历和后序遍历,以及插入、删除和查找操作。

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

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

相关文章

固态,机械,移动(U盘),sd卡,哪个更适合长期储存数据 保存数据用什么硬盘可靠 硬盘数据丢失怎么找回 硬盘维护注意事项

有关硬盘数据丢失的恢复技巧&#xff0c;这篇文章一定要收藏好。在硬盘使用过程中&#xff0c;很多情况都会导致数据丢失&#xff0c;例如硬盘跌落、病毒感染、系统文件损坏等。这时候&#xff0c;一定要采用正确的方法&#xff0c;抢救硬盘中存储的珍贵数据和文档。 有关长期保…

PO模式简介

V1顺序型&#xff1a;不能批量运行 import unittest from selenium import webdriver from time import sleep driver webdriver.Edge()# driver.maximize_window() driver.implicitly_wait(30) # driver.get(r"https://demo5.tp-shop.cn/") # driver.find_element…

Python 获取tiktok视频评论回复数据 api接口

TIKTOK api接口 用于爬取tiktok视频评论回复数据 详细采集页面如图 https://www.tiktok.com/dailymail/video/7329872821990182190?qneural%20link&t1706783508149 请求API http://api.xxxx.com/tt/video/info/comment/reply?video_id7288909913185701125&comment_…

【C++】指针的点运算与箭头运算(->)的奥秘与应用

在编程的世界里&#xff0c;指针作为连接程序与内存之间的桥梁&#xff0c;扮演着至关重要的角色。对于使用C、C等语言进行开发的程序员而言&#xff0c;理解并掌握指针的使用技巧是提升编程能力的必经之路。其中&#xff0c;指针的点运算&#xff08;.&#xff09;和箭头运算&…

Android系统集成和使用FFmpeg

文章目录 前言FFmpeg源码下载交叉编译NDK下载x264编译源码下载编译 FFmpeg编译脚本 AOSP继承FFmpeg 前言 原生AOSP中并未继承FFmpeg&#xff0c;所以要想在android上使用&#xff0c;需要自己编译集成。 FFmpeg源码下载 git clone https://git.ffmpeg.org/ffmpeg.git目前最新…

自动化测试报告pytest-html样式美化

最近我将 pytest-html 样式优化了 一版 先看优化前&#xff1a; 优化后&#xff1a; 优化内容包括&#xff1a; 删除部分多余字段新增echart图表部分字体大小、行间距、颜色做了美化调整运行环境信息移至报告最后部分字段做了汉化处理&#xff08;没全部翻译是因为&#xf…

vue3 引入百度地图的三种方式

本次也是正好写了一个基于VUE3和百度地图的设计&#xff0c;但奈何第一次使用百度地图&#xff0c;在学习的途中遇到了很多问题&#xff0c;也发现网上的材料相对较少&#xff0c;因此做出了一些小总结&#xff0c;后续还会更新。 一、直接引入 直接在public中的index.html中进…

[FreeRTOS 功能应用] 事件组 功能应用

文章目录 一、基础知识点二、代码讲解三、结果演示四、代码下载 一、基础知识点 [FreeRTOS 基础知识] 事件组 概念 [FreeRTOS 内部实现] 事件组 本实验是基于STM32F103开发移植FreeRTOS实时操作系统&#xff0c;事件组实战操作。(当task1和task2同时完成&#xff0c;才执行ta…

二维Gamma分布的激光点云去噪

目录 1、Gamma 分布简介2、实现步骤 1、Gamma 分布简介 Gamma 分布在合成孔径雷达( Synthetic Aperture &#xff32;adar&#xff0c;SA&#xff32;) 图像分割中具有广泛应用&#xff0c;较好的解决了SA&#xff32; 图像中相干斑噪声对图像分割的影响。采用二维Gamma 分布对…

Nginx Websocket 协议配置支持

前后分离的 Web 架构应用&#xff0c;在开发环境启动是可以直接连接支持 websocket 协议&#xff0c;因为没有中间件做转发处理。 当我们对前端进行编译后&#xff0c;通过 nginx 反向代理访问时&#xff0c;需要在nginx 配置文件中增加一些特定的头信息&#xff0c;让服务端识…

web前端开发——开发环境和基本知识

今天我来针对web前端开发讲解一些开发环境和基本知识 什么是前端 前端通常指的是网站或者Web应用中用户可以直接与之交互的部分&#xff0c;包括网站的结构、设计、内容和功能。它是软件开发中的一个专业术语&#xff0c;特别是指Web开发领域。前端开发涉及的主要技术包括HTML…

PySide(PyQt),记录最后一次访问文件的路径

1、在同目录下用文本编辑器创建JSON文件&#xff0c;命名为setting.json&#xff0c;并输入以下内容后保存&#xff1a; { "setting": { "last_file": [ "" ] } } 2、应用脚本&#xff1a; import json …

昇思25天学习打卡营第15天|linchenfengxue

Pix2Pix实现图像转换 Pix2Pix概述 Pix2Pix是基于条件生成对抗网络&#xff08;cGAN, Condition Generative Adversarial Networks &#xff09;实现的一种深度学习图像转换模型&#xff0c;该模型是由Phillip Isola等作者在2017年CVPR上提出的&#xff0c;可以实现语义/标签到…

Java常用算法集合扩容机制分析

基础篇 基础篇要点&#xff1a;算法、数据结构、基础设计模式 1. 二分查找 要求 能够用自己语言描述二分查找算法能够手写二分查找代码能够解答一些变化后的考法 算法描述 前提&#xff1a;有已排序数组 A&#xff08;假设已经做好&#xff09; 定义左边界 L、右边界 R&…

东芝TB6560AHQ/AFG步进电机驱动IC:解锁卓越的电机控制性能

作为一名工程师&#xff0c;一直在寻找可靠且高效的组件来应用于你的项目中。东芝的TB6560AHQ/AFG步进电机驱动IC能够提供精准且多功能的电机控制&#xff0c;完全符合现代应用的高要求&#xff0c;保证高性能和易用性。在这篇文章中&#xff0c;我们将探讨TB6560AHQ/AFG的主要…

硅纪元视角 | 国内首款鸿蒙人形机器人“夸父”开启应用新篇章

在数字化浪潮的推动下&#xff0c;人工智能&#xff08;AI&#xff09;正成为塑造未来的关键力量。硅纪元视角栏目紧跟AI科技的最新发展&#xff0c;捕捉行业动态&#xff1b;提供深入的新闻解读&#xff0c;助您洞悉技术背后的逻辑&#xff1b;汇聚行业专家的见解&#xff0c;…

es6新语法

es6新语法 1 什么是ES6 JS语法分三块 ECMAScript : 基础语法BOM 浏览器对象 history location windowDOM 文档对象 document 编程语言JavaScript是ECMAScript的实现和扩展 。ECMAScript是由ECMA&#xff08;一个类似W3C的标准组织&#xff09;参与进行标准化的语法规范。ECMAS…

03:C语言运算符

C语言运算符 1、常见运算符2、赋值运算符3、判断运算符4、与- - 1、常见运算符 数学运算符号。常见数学运算符号&#xff0c;跟数学中理解相同 加号 - 减号 * 乘号 / 除号&#xff0c;相除以后的商 % 取余符号&#xff0c;相除以后余数是几 ()括号括起来优先级最高&#xff0…

计算机网络面试常见题目(一)

计算机网络面试中常见的问题涉及多个层面&#xff0c;包括网络协议、网络体系结构、网络安全、数据传输等。以下是一些常见题目的详解&#xff1a; 1. OSI七层模型是什么&#xff1f;每层的功能是什么&#xff1f; OSI七层模型是国际标准化组织&#xff08;ISO&#xff09;制…

医疗器械企业CRM系统推荐清单(2024版)

近年来&#xff0c;我国医疗器械行业在国家政策支持、医改深入、人口老龄化和消费能力提升等因素推动下&#xff0c;得到了快速发展&#xff0c;正日益成为创新能力增强、市场需求旺盛的朝阳产业。然而&#xff0c;行业也面临价格压力、市场份额重新分配、合规风险以及产品和服…