首页 > 其他分享 >AVL树的插入

AVL树的插入

时间:2025-01-13 19:54:10浏览次数:1  
标签:直线型 子树 对于 AVL 插入 线型 所示 节点

关于AVL树的插入,其实是一个比较复杂的问题,主要是在于他对于“旋转”这一概念,对于这一概念其实我感觉很多博主讲的都不是很明白,包括CHATGPT,也试了,但是也没有比较清楚的解释,他们主要集中在一种比较简单的情况,即没有任何子树的情况,如下所示



对于这种最基本的平衡维护,确实不是一件困难的事情,这个可以作为一种技巧,来帮助我们快速的来去得到答案。所以在这里,我会先从最基本的情况来去讲解这里是怎么个操作的流程,这里会不用“旋转”这一概念来解释平衡的维护,而是一种更加简单易懂的方式来讲解。

(注  本次的博客会在发布之后补充上代码,现在不会添加代码,只是会提供相关的概念)

其实个人觉得看到不错的是这个,推荐一下便于大家学习https://www.hello-algo.com/chapter_tree/avl_tree/#2_1

OK。可恶的作者终于把他的废话说完了,现在开始要说内容了。

首先是对于这里的基本情况。

如下所示

可以看到是有四种情况,这里即是插入节点后失衡的四种情况。对于这四种情况,我们可以对他们做一个分类,分为直线型和弯线型。

为什么叫直线型和弯线型,其实在这里是非常明显的(这里当然很明显,但是对于实际的节点插入来说就不是特别明显了),我们将插入的节点向上回溯,然后一直到第一个失衡点,这样子来看,到达第一个失衡点之后,向下往插入点的方向标记三个单位,这个三个点就是接下来要主要操作的三个点了。

如下所示,

可以看到如上面的图片所示,可以知道,他为什么叫直线型和弯线型。那么接下来,就是如何对他们做操作呢,其实也是很简单的。

对于直线型,我们要做的就是把他掰弯,为了方便起见,我们将这三个点由上到下分别叫做爷爷,父亲,儿子。那么要做的是把爷爷弯折至和儿子一个高度,让后再将父亲给连接上。

对于弯线型,则是不一样,我们要先将它弄直,然后再像直线型一样操作。对于再将弯线型弄直的过程中,由于他是一个二叉树,所以要将父亲和儿子的值给交换一下,这样子才可以让其维持二叉树的特点。

那么这种最基本的情况讲完了,但是这并不足以应付一些复杂的情况,如果说存在子树的话,那么怎么去移动父亲,儿子,爷爷三个点的子树就成为了问题。

那么如下所示

对于这样子一个二叉树,我应该怎么去维护他的平衡性。可以按照如下的操作。

首先我们要先找到他的不平衡点,我们去依次标记他的子树的大小,如下所示

可以知道当前的为直线型,爷爷,父亲,儿子分别为4,7,15三个点,那么由于是直线型,那么父亲必然是要作为接下来的新根节点,但是问题是此时,由于他是在中间位置,如果我直接去做弯折的操作,就会导致他的子树无法处理(总不能直接变成三叉树吧),所以这个时候,我需要做的是对他的子树进行转移。

如何转移他的子树呢,对于由于此时爷爷节点在下移了之后,他的位置有一个子树的位置是空了,所以在这里可以把子树转移到他的爷爷节点下面,转移之后,如下所示

实际上,我们就是将节点转移到了爷爷上面,并且把父亲作为了新的根节点。

那么对于有子树的弯折型,又应该怎么处理呢,可以参考如下的例子。在这里,已经标记好了弯折点。

在这里,接下来要做的就是去首先将它给掰直,在掰直的过程中,可以发现由于16的存在,影响了掰直,所以在这里的处理措施是将将7移动到与6连接的地方,在这之后,就是将15节点移动下来,并将14节点拼接到15节点上,这样,就完成了一次移动,完成后的结果如下所示。
之后,我们可以看到他接下来就可以弄弯了。

这样子,我们就可以实现对他的平衡的维护了。

最后总结一下吧。

1.对于直线型,我们要做的是将它儿子的那个不在线上的子树给他的父亲节点,这样子就可以完成平衡的维护

2.对于弯线型,则可以去将其儿子的子树给到父亲节点,然后将儿子放在中间位置,在这之后,就是做和直线型一样的操作。

标签:直线型,子树,对于,AVL,插入,线型,所示,节点
From: https://www.cnblogs.com/fufufuf/p/18669306

相关文章

  • #1407. 字符串的插入
    题目描述输入一个句子(一行),将句子中的每一个单词翻转后输出。输入格式只有一行,为一个字符串,不超过500个字符。单词之间以空格隔开。输出格式翻转每一个单词后的字符串,单词之间的空格需与原文一致。输入数据1helloworld输出数据1ollehdlrow代码:#include<iostr......
  • 插入排序
    插入排序(InsertionSort)是一种简单直观的排序算法,它的工作原理类似于扑克牌的整理过程。在摸牌时,玩家会将每张新摸到的牌插入到手中已有的有序牌中的合适位置。1.算法步骤初始状态:将数组分为已排序和未排序两部分。初始时,数组的第一个元素被认为是已排序部分,其余元素是未排序......
  • 【YashanDB知识库】使用DBeaver 插入数据 nvarchar字段插入为空
    本文内容来自YashanDB官网,原文内容请见https://www.yashandb.com/newsinfo/7901516.html?templateId=1718516【问题分类】DBeaver使用【关键字】DBeaver、nvarchar【问题描述】使用DBeaver,插入数据nvarchar字段插入为空。其他字段都有数据,且插入没有报错。【问题原因分析】......
  • 力扣-数组-35 搜索插入位置
    解析时间复杂度要求,所以使用二分的思想,漏掉了很多问题,这里记录在left-right=1时,已经找到了插入位置,但是没有赋值,然后break,所以导致一直死循环。if(right-left==1){result=right;break;}在和最右侧数比较时,漏掉了相等时就直接找到,所以在数组是[1,3],target......
  • 算法浅谈:插入-标记-查找
    前言lxl的课属实让我受益匪浅,这篇博客就来谈一谈他自创的算法:插入-标记-查找算法概述这是一个离线算法,用到了扫描线思想和数据结构,它可以秒掉这样一类问题:给定\(n\)个映射\(f_i(x)\;(i\in[1,n])\)和\(m\)个询问每个询问形如给定\(x,l,r\)求\(f_r(f_{r-1}(\dots......
  • 57. 插入区间
    题目名称插入区间题目叙述给你一个无重叠的,按照区间起始端点排序的区间列表。在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。示例1:输入:intervals=[[1,3],[6,9]],newInterval=[2,5]输出:[[1,5],[6,9]]示例2:......
  • 直接插入排序讲解
    直接插入排序定义算法步骤复杂度分析代码示例(C)代码分析1.打印数组模块2.直接插入排序模块3.主函数模块图示过程初始状态第一轮排序(插入`11`)第二轮排序(插入`13`)第三轮排序(插入`5`)第四轮排序(插入`6`)运行流程图解最终结果优缺点定义直接插入排序是一种简单直......
  • 单链表的一些操作(c语言):插入头节点、尾节点、删除某个节点
    #include<stdio.h>#include<stdlib.h>structNode{  intdata;  structNode*Next;  /*data*/};typedefstructNodenode;node*Link;// 创建一个新的节点node*CreateNewNode(intdata){  node*NewNode=(node*)malloc(sizeof(node......
  • BST和AVL
    二叉搜索树binarysearchtree和平衡二叉搜索树AVL#include<iostream>usingnamespacestd;structTreeNode{intval;TreeNode*left;TreeNode*right;intheight;TreeNode(intvalue):val(value),left(nullptr),right(nullptr){}};classBST......
  • MySQL优化--插入数据优化和主键优化
    一、插入数优化(insert)平时我们插入数据的时候一般都是一个语句插一个数据,如下所示:insertintotb_testvalues(1,'tom');insertintotb_testvalues(2,'cat');insertintotb_testvalues(3,'jerry');如果我们需要一次性往数据库表中插入多条记录,可以从以下三个方面进行优......