数据结构之平衡二叉搜索树

news/发布时间2024/5/18 15:13:08

什么是平衡二叉树

AVL是一种自平衡二叉搜索树(self-balancing binary search tree)的数据结构,它的名称来源于其发明者G.M. Adelson-Velsky和E.M. Landis。AVL树通过在每次插入或删除节点时进行旋转操作,来确保树的高度始终保持在一个较小的范围内,从而保持树的平衡性。

AVL树的平衡性是通过节点的高度差(即左子树高度和右子树高度之差)来衡量的。在一个平衡的AVL树中,任何节点的左子树和右子树的高度差不超过1。当插入或删除节点导致某个节点的平衡被打破时,AVL树会通过旋转操作来恢复平衡。AVL树的旋转操作分为四种类型:左旋、右旋、左右旋和右左旋。左旋和右旋用于处理节点的子树高度差为2的情况,而左右旋和右左旋用于处理节点的子树高度差为-2的情况。通过这些旋转操作,AVL树可以在插入或删除节点时保持平衡,并且可以在O(log n)的时间复杂度内进行插入、删除和查找操作。AVL树在许多应用中都有广泛的应用,特别是在需要高效的插入、删除和查找操作的场景中。它是一种重要的数据结构,被用于数据库、编译器、操作系统等领域。

旋转操作

 

 

 

 

示例代码

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>#define HEIGHT(p) ((p==NULL)?-1:(p->height))
#define MAX(a,b) ((a)>(b)?(a):(b))typedef struct 
{int key;char value[20];
}Data;typedef struct AVLTreeNode 
{Data data;int height;struct AVLTreeNode* LChild;struct AVLTreeNode* RChild;
}Node;
//创建节点
Node* create_node(Data data) 
{Node* newNode = (Node*)malloc(sizeof(Node));assert(newNode);newNode->data = data;newNode->height = 0;newNode->LChild = NULL;newNode->RChild = NULL;return newNode;
}
//层次遍历
void print_tree(Node* tree)
{if (tree == NULL)return;Node* pmove = tree;Node* queue[1024];int front = 0;int tail = 0;queue[tail++] = pmove;printf("%d:%s\n", pmove->data.key, pmove->data.value);while (front != tail){pmove = queue[front++];if (pmove->LChild != NULL){queue[tail++] = pmove->LChild;printf("%d:%s\n", pmove->LChild->data.key, pmove->LChild->data.value);}else{printf("NULL\n");}if (pmove->RChild != NULL){queue[tail++] = pmove->RChild;printf("%d:%s\n", pmove->RChild->data.key, pmove->RChild->data.value);}else {printf("NULL\n");}}
}
//LL
Node* ll_rotation(Node* k2) 
{//旋转Node* k1 = k2->LChild;k2->LChild = k1->RChild;k1->RChild = k2;//节点高度k2->height = MAX(HEIGHT(k2->LChild), HEIGHT(k2->RChild)) + 1;k1->height = MAX(HEIGHT(k1->LChild), k2->height) + 1;return k1;
}
//RR
Node* rr_rotation(Node* k1) 
{Node* k2 = k1->RChild;k1->RChild = k2->LChild;k2->LChild = k1;k1->height = MAX(HEIGHT(k1->LChild), HEIGHT(k1->RChild)) + 1;k2->height = MAX(HEIGHT(k2->LChild), k1->height) + 1;return k2;
}
//LR
Node* lr_rotation(Node* k3) 
{k3->LChild = rr_rotation(k3->LChild);return ll_rotation(k3);}
//RL
Node* rl_rotation(Node* k3) 
{k3->RChild = ll_rotation(k3->RChild);return rr_rotation(k3);
}Node* insert_avl(Node* tree, Data data) 
{if (tree == NULL)tree = create_node(data);else if (data.key < tree->data.key) {tree->LChild = insert_avl(tree->LChild, data);if (HEIGHT(tree->LChild) - HEIGHT(tree->RChild) == 2) {if (data.key < tree->LChild->data.key) {tree = ll_rotation(tree);}else {tree = lr_rotation(tree);}}}else if (data.key > tree->data.key) {tree->RChild = insert_avl(tree->RChild, data);if (HEIGHT(tree->RChild) - HEIGHT(tree->LChild) == 2) {if (data.key > tree->RChild->data.key) {tree = rr_rotation(tree);}else {tree = rl_rotation(tree);}}}else {printf("插入失败!关键字唯一!\n");}tree->height = MAX(HEIGHT(tree->LChild), HEIGHT(tree->RChild)) + 1;return tree;
}
Node* max_node(Node* tree) 
{if (tree == NULL)return NULL;while (tree->RChild != NULL) {tree = tree->RChild;}return tree;
}
Node* min_node(Node* tree)
{if (tree == NULL)return NULL;while (tree->LChild != NULL) {tree = tree->LChild;}return tree;
}
Node* erase_avl(Node* tree, int key)
{if (tree == NULL)return NULL;if (key < tree->data.key){tree->LChild = erase_avl(tree->LChild, key);if (HEIGHT(tree->RChild) - HEIGHT(tree->LChild) == 2){Node* rightNode = tree->RChild;if (rightNode != NULL && HEIGHT(rightNode->LChild) > HEIGHT(rightNode->RChild)){tree = rl_rotation(tree);}else{tree = rr_rotation(tree);}}}else if (key > tree->data.key){tree->RChild = erase_avl(tree->RChild, key);if (HEIGHT(tree->LChild) - HEIGHT(tree->RChild) == 2){Node* leftNode = tree->LChild;if (leftNode != NULL && HEIGHT(leftNode->RChild) > HEIGHT(leftNode->LChild)){tree = lr_rotation(tree);}else{tree = ll_rotation(tree);}}}else{if (tree->LChild != NULL && tree->RChild != NULL) {if (HEIGHT(tree->LChild) > HEIGHT(tree->RChild)) {Node* max = max_node(tree->LChild);tree->data = max->data;tree->LChild = erase_avl(tree->LChild, max->data.key);}else {Node* min = min_node(tree->RChild);tree->data = min->data;tree->RChild = erase_avl(tree->RChild, min->data.key);}}else {Node* temp = tree;tree = tree->LChild ? tree->LChild : tree->RChild;free(temp);}}return tree;
}void test_avl()
{Data data[10] = { 0,"小美",1,"小芳",2,"小丽",3,"小小",4,"悠悠",5,"小妹",6,"小梅",7,"小爱",8,"笑笑",9,"筱花" };Node* root = NULL;for (int i = 0; i < 10; i++) {root = insert_avl(root, data[i]);}print_tree(root);printf("----------------------\n");root=erase_avl(root, 7);print_tree(root);
}
int main() 
{test_avl();return 0;
}

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

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

相关文章

”戏说“ 交换机 与 路由器

一般意义上说 老哥 这文章发表 的 东一榔头 西一锤 呵呵&#xff0c; 想到哪里就啰嗦到哪里 。 交换机&#xff1a; 其实就是在通道交换 路由器&#xff1a; 不光是在通道交换还要在协议上交换 下图你看懂了吗&#xff1f; &#xff08;仅仅数据交换-交换机 协议…

国产chat gpt推荐

下述网站响应非常快 会持续更新的! 付费&#xff1a; 小名言 免费&#xff1a; AIchatOS 百度的文心一言

HTTP 与 HTTPS-HTTP 解决了 HTTP 哪些问题?

资料来源 : 小林coding 小林官方网站 : 小林coding (xiaolincoding.com) HTTP 解决了 HTTP 哪些问题? HTTP 由于是明文传输&#xff0c;所以安全上存在以下三个风险: 窃听风险&#xff0c;比如通信链路上可以获取通信内容&#xff0c;用户号容易没。篡改风险&#xff0c;比如…

SMIC思洣客矩阵:重塑数字经济的未来

经济的发展 经济是供需满足的过程&#xff0c;它涵盖了社会物资的生产和再生产过程。在这个过程中&#xff0c;经济活动遵循着生产和再生产的规律&#xff0c;通过生产、分配、交换和消费的过程&#xff0c;不断地形成和再造价值。从传统的市场经济到现代的智能经济&#xff0…

Flink checkpoint操作流程详解与报错调试方法汇总,增量checkpoint原理及版本更新变化,作业恢复和扩缩容原理与优化

Flink checkpoint操作流程详解与报错调试方法汇总&#xff0c;增量checkpoint原理及版本更新变化&#xff0c;作业恢复和扩缩容原理与优化 flink checkpint出错类型flink 重启策略Checkpint 流程简介增量Checkpoint实现原理MemoryStateBackend 原理FsStateBackend原理RocksDBSt…

ARM服务器部署Kafka集群

安装前必备的条件是: (1)安装jdk(提供环境); (2)安装zookeeper(注册kafka信息); 需要这方面信息的可以查看我之前写的文档; 一.下载安装包 Kafka官网下载地址 Apache Kafka 根据自己需要下载相应的版本 目前最新的版本是3.6.1。 二.解压安装包 服务器上传下载好的kafk…

【vue】如何打开别人编译后的vue项目

文件结构如下&#xff0c;编译后的文件放在dist中。 dist的文件结构大约如下&#xff0c;文件名称随项目 1.新建app.js文件 const express require(express);const app express();const port 8080;app.use(express.static(dist));app.listen(port, () > console.log); …

Java 泛型

优质博文&#xff1a;IT-BLOG-CN 一、为什么要有泛型 【1】解决元素存储的安全性问题。 【2】解决获取数据元素时&#xff0c;需要类型强转的问题。 【3】可以统一数据类型&#xff0c;便于操作。 【4】将运行时的异常提前到了编译时&#xff0c;提高了效率。 【5】实现代码的…

已知路径点(x,y)系列坐标如何利用matlab中自带的函数求解曲率值

以Trucksim的路径为例 路径 坐标点 将路径点以mat格式存储在matlab中如下图 4.下面展示 matlab代码。 // 将Ref_Road_Points数据进行类型转化 yyreferencePathFrenet(Ref_Road_Points) //数据一共201个点 将s设置为列向量 s(1:201); kappacurvature(yy,s);注意matlab中这…

对Redis锁延期的一些讨论与思考

上一篇文章提到使用针对不同的业务场景如何合理使用Redis分布式锁&#xff0c;并引入了一个新的问题 若定义锁的过期时间是10s&#xff0c;此时A线程获取了锁然后执行业务代码&#xff0c;但是业务代码消耗时间花费了15s。这就会导致A线程还没有执行完业务代码&#xff0c;A线程…

我是怎么用静态IP代理为Google账号保驾护航的

我为何要使用到静态IP代理服务 我是一名IT从业者&#xff0c;在很多年前就加入了一家跨国软件公司&#xff0c;日常需要在全世界各地跟甲方沟通&#xff0c;负责的工作中重要的一块就是Google广告&#xff0c;为此公司还特意给配置了一台笔记本电脑。 目录 我为何要使用到静态…

会声会影2024视频编辑软件电脑版本下载

一、功能特点 会声会影是一款功能强大的视频编辑软件&#xff0c;它集合了视频剪辑、特效添加、音频处理、字幕制作等多种功能于一身。具体来说&#xff0c;其特点包括&#xff1a; 会声会影2024安装包下载如下: https://wm.makeding.com/iclk/?zoneid55677 直观易用的操作…

Polyspace静态检测步骤

Polyspace 是一个代码静态分析和验证的工具&#xff0c;隶属于MATLAB&#xff0c;用于检测代码中的错误和缺陷&#xff0c;包括内存泄漏、数组越界、空指针引用等。帮助开发团队提高代码质量&#xff0c;减少软件开发过程中的错误和风险。 1、打开MATLAB R2018b 2、找到Polys…

【论文阅读】ICASSP 2023 针对目标检测的无目标后门攻击

文章目录 一.论文信息二.论文内容1.摘要2.引言3.作者贡献4.主要图表5.结论 一.论文信息 论文题目&#xff1a; Untargeted backdoor attack against object detection&#xff08;针对目标检测的无目标后门攻击&#xff09; 论文来源&#xff1a; 2023-ICASSP&#xff08;CCF…

Flutter(二):Row、Column 布局

MaterialApp 对于 MaterialApp&#xff0c;组件提供了一些默认的属性&#xff0c;如AppBar、标题、背景颜色等&#xff0c;你可以默认使用它们 import package:flutter/material.dart;void main() {runApp(const App()); }class App extends StatelessWidget {const App({super…

问题慢慢解决-通过android emulator调试android kernel-内核条件断点遇到的问题和临时解决方案

起因 在摸索到这个方案之后&#xff0c;mac m1调试aarch64 android kernel最终方案&#xff0c;就准备调试内核了&#xff0c;预备下断点的地方是 b binder_poll b ep_ptable_queue_proc b remove_wait_queue但是由于是android系统&#xff0c;上面三个函数会被频繁的触发&am…

基于PID控制器的直流电机位置控制系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 1. PID控制器原理 2. 位置控制环 5.完整工程文件 1.课题概述 基于PID控制器的直流电机位置控制系统。直流电机位置控制系统是工业自动化领域中的一个重要应用。为了实现精确的位置控制&#xff0c;常采…

3ds Max视频怎么渲染 3ds Max云渲染操作

在3ds Max软件中制作视频动画本质上是逐帧生成画面&#xff0c;并将这些连续帧串联起来创造出动态连贯的视觉效果。常见的视频帧率包括25 FPS(每秒帧数)、60 FPS、以及120 FPS等&#xff0c;帧率的提升可以使视频动画更加流畅。在实质上&#xff0c;视频渲染就是动画渲染&#…

什么是汽车抛负载Load dump

1.什么是抛负载 抛负载&#xff0c;英文为Load dump&#xff0c;是指断开电源与负载的瞬间&#xff0c;由于负载突变而引起电源电压急剧变化。在汽车电子领域&#xff0c;抛负载是指在蓄电池充电时&#xff0c;断开发电机与蓄电池的连接而引起发电机输出大电压尖峰&#xff0c…

使用React 18、Echarts和MUI实现温度计

关键词 React 18 Echarts和MUI 前言 在本文中&#xff0c;我们将结合使用React 18、Echarts和MUI&#xff08;Material-UI&#xff09;库&#xff0c;展示如何实现一个交互性的温度计。我们将使用Echarts绘制温度计的外观&#xff0c;并使用MUI创建一个漂亮的用户界面。 本文…
推荐文章