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

什么是平衡二叉树

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.hqwc.cn/news/488357.html

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

相关文章

C语言——实用调试技巧——第1篇——(第22篇)

坚持就是胜利 文章目录 一、什么是bug?二、调试是什么&#xff1f;有多重要&#xff1f;三、debug 和 release 的介绍&#xff1f;1、2、3、 四、windows环境调试介绍1、调试环境的准备2、学会快捷键F5 或者 Fn F5条件断点 Ctrl F5F9 或者 Fn F9F10 或者 Fn F10F11 或者 F…

C语言读取 ini 配置文件,修改/添加键值对

C语言读取 ini 配置文件&#xff0c;修改/添加键值对 C语言读取 ini 配置文件&#xff0c;对section中的键值对进行修改/添加&#xff0c;如果section不存在&#xff0c;则在末尾将新的section/key/value 添加进去。 一、了解什么是INI文件&#xff1f; ini 文件是Initializ…

unity Aaimation Rigging使用多个约束导致部分约束失去作用

在应用多个约束时&#xff0c;在Hierarchy的顺序可能会影响最终的效果。例如先应用了Aim Constraint&#xff0c;然后再应用Two Bone Constraint&#xff0c;可能会导致Two Bone Constraint受到Aim Constraint的影响而失效。因此&#xff0c;在使用多个约束时&#xff0c;应该仔…

5G网络(接入网+承载网+核心网)

5G网络&#xff08;接入网承载网核心网&#xff09; 一、5G网络全网架构图 这张图分为左右两部分&#xff0c;右边为无线侧网络架构&#xff0c;左边为固定侧网络架构。 无线侧&#xff1a;手机或者集团客户通过基站接入到无线接入网&#xff0c;在接入网侧可以通过RTN或者IP…

【坑】Spring Boot整合MyBatis,一级缓存失效

一、Spring Boot整合MyBatis&#xff0c;一级缓存失效 1.1、概述 MyBatis一级缓存的作用域是同一个SqlSession&#xff0c;在同一个SqlSession中执行两次相同的查询&#xff0c;第一次执行完毕后&#xff0c;Mybatis会将查询到的数据缓存起来&#xff08;缓存到内存中&#xf…

Vue2页面转化为Vue3

vue2element-ui转化为Vue3element plus 后台管理系统&#xff1a;增删查改 vue2页面&#xff1a; <template><div class"app-container"><div><el-form:model"queryParams"ref"queryForm"size"small":inline&qu…

Stable Diffusion 3 震撼发布,采用Sora同源技术,文字终于不乱码了

Stable Diffusion 3 和 Sora 一样采用了 diffusion transformer 架构。 继 OpenAI 的 Sora 连续一周霸屏后&#xff0c;昨晚&#xff0c;生成式 AI 顶级技术公司 Stability AI 也放了一个大招 ——Stable Diffusion 3。该公司表示&#xff0c;这是他们最强大的文生图模型。 与…

2024年 Openai的API相关全部概论汇总(通用版)

2024年 Openai的API相关全部概论汇总&#xff08;通用版&#xff09; 文章目录 2024年 Openai的API相关全部概论汇总&#xff08;通用版&#xff09;一、前言1、python快速开始 二、Openai 平台以及相关项目1、Openai的API管理平台2、ChatGPT项目推荐&#xff08;1&#xff09;…

会声会影2024官方重磅发布更新内径讲解介绍

一、功能特点 会声会影2024作为一款专业的视频编辑软件&#xff0c;继承了之前版本的强大功能&#xff0c;并进行了诸多创新和改进。其主要功能特点包括&#xff1a; 多轨时间轴编辑&#xff1a;支持多轨音视频同时编辑&#xff0c;便于用户精细调整各个元素的时间和位置。丰…

2024年 前端JavaScript入门到精通 第四天 笔记

4.1 函数的基本使用以及封装练习 ★ 函数命名规范 4.2 函数的参数以及默认参数 函数的灵魂&#xff01;&#xff01;&#xff01; 4.3 函数封装数组求和案例 4.4 函数返回值return 4.5 函数返回值细节以及上午总结 4.6 函数返回值案例-求最大值和最 4.7 函数复习以及断点进入函…

【补充】linux内核升级

目录 步骤一&#xff1a;准备内核下载的repo文件 步骤二&#xff1a;yum安装lt长期稳定版 步骤三&#xff1a;查看内核序号&#xff0c;并绑定开机启动选择的序号 步骤四&#xff1a;重启查看 查看当前的内核版本 步骤一&#xff1a;准备内核下载的repo文件 内核升级 cat …

RISC-V知识总结 —— 指令集

资源1: RISC-V China – RISC-V International 资源2: RISC-V International – RISC-V: The Open Standard RISC Instruction Set Architecture 资源3: RV32I, RV64I Instructions — riscv-isa-pages documentation 1. 指令集架构的类型 在讨论RISC-V或任何处理器架构时&…