AVL树是一种自平衡(Self-balancing)二叉查找树(Binary Search Tree),要求任何一个节点的左子树和右子树的高度之差不能超过1。

AVL树的插入操作首先会按照普通二叉查找树的插入操作进行,不同的是在成功插入一个节点后会向上进行回溯,判断路径中的每一个节点左子树和右子树高度之差,如果相差大于1,则进行旋转操作使得树重新达到平衡状态,旋转的本质其实是为当前不平衡的子树选择一个新的根节点,以降低两侧的高度差。

这里以root表示不平衡节点(左右子树高度差大于1),旋转操作可分为以下四种:

  • 右旋转:当加入的节点在root的左子节点的左子树中(LL),以root为轴进行一次右旋转。
  • 左旋转:当加入的节点在root的右子节点的右子树中(RR),以root为轴进行一次左旋转。
  • 左右旋转:当加入的节点在root的左子节点的右子树中(LR),先以root的左子节点为轴进行一次左旋转,再以root为轴进行一次右旋转。
  • 右左旋转:当加入的节点在root的右子节点的左子树中(RL),先以root的右子节点为轴进行一次右旋转,再以root为轴进行一次左旋转。

代码如下:

#include <cstdio>
#include <cstdlib>
#define max(x, y) (((x) > (y)) ? (x) : (y))
typedef struct tnode
{
int val;
struct tnode * left;
struct tnode * right;
} node; //LL:右旋转
node * rotate_right(node * root) {
node * lnode = root->left;
root->left = lnode->right;
lnode->right = root;
return lnode;
} //RR:左旋转
node * rotate_left(node * root) {
node * rnode = root->right;
root->right = rnode->left;
rnode->left = root;
return rnode;
} //LR:先左旋转,再右旋转
node * rotate_left_right(node * root) {
root->left = rotate_left(root->left);
return rotate_right(root);
} //RL:先右旋转,再左旋转
node * rotate_right_left(node * root) {
root->right = rotate_right(root->right);
return rotate_left(root);
} //递归求得以root为根节点的树的高度
int get_height(node * root) {
if (root == NULL) return 0;
return max(get_height(root->left), get_height(root->right)) + 1;
} //在以root为根节点的树中插入值为val的节点
node * insert(node * root, int val) {
if (root == NULL) {
root = (node *) malloc(sizeof(node));
root->val = val;
root->left = NULL;
root->right = NULL;
} else if (val < root->val) {
root->left = insert(root->left, val);
if (get_height(root->left) - get_height(root->right) == 2) {
if (val < root->left->val) root = rotate_right(root);
else root = rotate_left_right(root);
}
} else {
root->right = insert(root->right, val);
if (get_height(root->right) - get_height(root->left) == 2) {
if (val > root->right->val) root = rotate_left(root);
else root = rotate_right_left(root);
}
} return root;
} int main(void) {
int n, val;
node * root = NULL; scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &val);
root = insert(root, val);
} return 0;
}

AVL树的创建--C语言实现的更多相关文章

  1. 数据结构--Avl树的创建,插入的递归版本和非递归版本,删除等操作

    AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树.   2.带有平衡条件:每个结点的左右子树的高度之差的绝对值最多为1(空树的高度为-1).   也就是说,AVL树,本质上 ...

  2. 数据结构与算法(九):AVL树详细讲解

    数据结构与算法(一):基础简介 数据结构与算法(二):基于数组的实现ArrayList源码彻底分析 数据结构与算法(三):基于链表的实现LinkedList源码彻底分析 数据结构与算法(四):基于哈希 ...

  3. 二叉查找树(BST)、平衡二叉树(AVL树)(只有插入说明)

    二叉查找树(BST).平衡二叉树(AVL树)(只有插入说明) 二叉查找树(BST) 特殊的二叉树,又称为排序二叉树.二叉搜索树.二叉排序树. 二叉查找树实际上是数据域有序的二叉树,即对树上的每个结点, ...

  4. 二叉查找树(BST)、平衡二叉树(AVL树)

    二叉查找树(BST) 特殊的二叉树,又称为排序二叉树.二叉搜索树.二叉排序树. 二叉查找树实际上是数据域有序的二叉树,即对树上的每个结点,都满足其左子树上所有结点的数据域均小于或等于根结点的数据域,右 ...

  5. AVL树原理及实现(C语言实现以及Java语言实现)

    欢迎探讨,如有错误敬请指正 如需转载,请注明出处http://www.cnblogs.com/nullzx/ 1. AVL定义 AVL树是一种改进版的搜索二叉树.对于一般的搜索二叉树而言,如果数据恰好 ...

  6. AVL树(一)之 图文解析 和 C语言的实现

    概要 本章介绍AVL树.和前面介绍"二叉查找树"的流程一样,本章先对AVL树的理论知识进行简单介绍,然后给出C语言的实现.本篇实现的二叉查找树是C语言版的,后面章节再分别给出C++ ...

  7. AVL树(查找、插入、删除)——C语言

    AVL树 平衡二叉查找树(Self-balancing binary search tree)又被称为AVL树(AVL树是根据它的发明者G. M. Adelson-Velskii和E. M. Land ...

  8. Avl树的基本操作(c语言实现)

    #include<stdio.h> #include<stdlib.h> typedef struct AvlNode *Position; typedef struct Av ...

  9. 深入浅出数据结构C语言版(12)——平衡二叉查找树之AVL树

    在上一篇博文中我们提到了,如果对普通二叉查找树进行随机的插入.删除,很可能导致树的严重不平衡 所以这一次,我们就来介绍一种最老的.可以实现左右子树"平衡效果"的树(或者说算法),即 ...

随机推荐

  1. 飞机大战-面向对象-pygame

    飞机大战 最近学习了python的面向对象,对面向对象的理解不是很深刻. 面向对象是数据和函数的'打包整理',将相关数据和处理数据的方法集中在一个地方,方便使用和管理. 本着学习的目的,在网上找了这个 ...

  2. mysql备份及恢复

    第四章:MySQL数据库的备份与恢复                            2016-09-30 00:58:05 标签:数据库备份 工作原理 数据库表 mysql source 原创 ...

  3. Clickhouse 时区转换(下)

    Clickhouse 时区转换续—时区参数转换 天天加班,时间不够,主要还是我太懒,流汗,,,,,,另外如果这篇学习笔记超过100阅读量并有评论,我可能半夜也会爬起来更新的. 相信大家看我之前记录的这 ...

  4. inotify-tools的inotifywait工具用exclude 和 fromfile 排除指定后缀文件

    今天打算使用 inotify-tool 来对线上程序文件进行监控, 因为有些目录是缓存目录, 所以要进行排除, 同时还要排除一些指定的后缀的文件, 比如 .swp 等 需要递归监控的目录为: /tmp ...

  5. 51NOD 2072 装箱问题 背包问题 01 背包 DP 动态规划

    有一个箱子容量为 V(正整数,0<=V<=20000),同时有 n 个物品(0<n<=30),每个物品有一个体积(正整数). 现在在 n 个物品中,任取若干个装入箱内,使得箱子 ...

  6. python(re 模块)

    1.re.match() 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none. group() 以str形式返回对象中match的元素 start() 返回 ...

  7. python(格式化输出)

    一.%格式化输出 1.整数的输出(参照ASCII) %o —— oct 八进制 %d —— dec 十进制(digit ) %x —— hex 十六进制 >>> print('%o' ...

  8. IoTClientTool自动升级更新

    IoTClientTool是什么 IoTClientTool是什么,IoTClientTool是IoTClient开源组件的可视化操的作实现.方便对plc设备和ModBusRtu.BACnet.串口等 ...

  9. Java 常用API(一)

    目录 Java 常用API(一) 1. Scanner类 引用类型的一般使用步骤 Scanner的使用步骤 例题 2. 匿名对象 概述 匿名对象作为方法的参数 匿名对象作为方法的返回值 3. Rand ...

  10. Spring Boot学习 之 Spring Boot Actuator(一)

    Spring Boot版本:2.1.4.RELEASE 启用: spring-boot-actuator模块提供了一系列的用于监控的端点.最简单的开启这个功能的方法就是,在pom文件中添加如下的依赖. ...