avl树 golang实现

golang实现高度平衡二叉树(AVL树) AVL树简介 AVL 树是高度相对平衡(abs(height(node.lchild - height(node.rchild) < 2))的二叉搜索树。它和二叉搜索树主要的区别在AVL是高度平衡的,不会出现二叉搜索树极端情况:线性链表 搜索复杂度为N 。 实现上,AVL树在插入节点和删除节点时要不断调整树,使其处在一个平衡状态。和二叉搜索树相比主要增加树旋转、调整。 实现源码 ... 阅读详情

#Tree


术语:
- 树
- 根
- 节点
- 叶子
- 层次, 根节点
- 深度
- 树的高度, 空树的深度为`-1`, 根的深度为`0`, 一个节点的高度为`0`, 所有的树叶的高度都为`0`。


---


##二叉树
每个节点最多有两个孩子,空树也是一棵二叉树,链表是一种特殊的二叉树。


## 二叉排序树(二叉搜索树,B树)


## 满二叉树


## 完全二叉树


## AVL树
AVL树本质上还是一棵二叉搜索树(因此读者可以看到我后面的代码是继承自二叉搜索树的),它的特点是:


1. 本身首先是一棵二叉搜索树。 
2. 带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1。 


例如:
```
     5              5
    / \            / \
   2   6          2   6
  / \   \        / \
 1   4   7      1   4
    /              /
   3              3
```
上图中,左边的是AVL树,而右边的不是。因为左边的树的每个结点的左右子树的高度之差的绝对值都最多为1,而右边的树由于结点6没有子树,导致根结点5的平衡因子为2。


假设有一个结点的平衡因子为2(在AVL树中,最大就是2,因为结点是一个一个地插入到树中的,一旦出现不平衡的状态就会立即进行调整,因此平衡因子最大不可能超过2),那么就需要进行调整。由于任意一个结点最多只有两个儿子,所以当高度不平衡时,只可能是以下四种情况造成的:


- 对该结点的左儿子的左子树进行了一次插入(`LL`)。


- 对该结点的左儿子的右子树进行了一次插入(`LR`)。


- 对该结点的右儿子的左子树进行了一次插入(`RL`)。


- 对该结点的右儿子的右子树进行了一次插入(`RR`)。


情况1和4是关于该点的镜像对称,同样,情况2和3也是一对镜像对称。因此,理论上只有两种情况,当然了,从编程的角度来看还是四种情况。


第一种情况是插入发生在“外边”的情况(即左-左的情况或右-右的情况),该情况可以通过对树的一次单旋转来完成调整。第二种情况是插入发生在“内部”的情况(即左-右的情况或右-左的情况),该情况要通过稍微复杂些的双旋转来处理。




`旋转:`


###单旋转
情况1(`LL`):对该结点的左儿子的左子树进行了一次插入。
![](http://blog.chinaunix.net/attachment/201108/14/25324849_1313308607C3xL.jpg)




左边为调整前得节点,我们可以看出k2的左右子树已不再满足AVL平衡条件,调整后的为右图。


由于K2的左孩子已经变大了,所以应该降低K1的高度,把K1往上提,而K2相应也得往下降。k2下降在k1的右子树(因为k1的左子树增加了,所以不可能再把k2降到k1的左子树上),Y变为K2的左子树(如果Y变成K2的有子树,那么k2的本身没有了左子树,还降为右子树,那么就一减一加,左右失调,平衡因子变成2)。


情况2(`LR`):对该节点的左孩子进行了一次插入
![](../../pic/2676FCA1-CF64-48B2-B4A7-73C41E8C16A7.png)


先从最先失去平衡的节点开始分析,B的left为h,right为h+2,失去平衡,c往上提,B往下提,以致降低整棵树的高度(可以理解为`B,Bl,C,Cl,Cr`这颗树,先把A ignore),C已经平衡,但是A失去平衡,C往上提,A往下降,以致降低整棵树(`C,A,Ar`),Cr连到A的left防止A的right变大而失去平衡,最终C,B,A都已经平衡。


其实他们之间的方法都是一致的,高的节点往上提已经降低其高度,高的往下提,增加高度。这里的***高度可以理解为树的高度***, 他们采用的是一种策略,这是一种平衡左右子树的`趋势`


情况3(`RR`):


![](../../pic/7109344F-642A-4AC0-9F89-9B576FB59578.png)




情况4(`RL`)


![](../../pic/1CB097E6-D404-4CEC-8442-1DE3B3096A52.png)
实现代码:


---
---


## B-树,B+树


---


---




package main

import (
	"fmt"
)

type DataType int
type Node AVLTreeNode
type AVLTree *AVLTreeNode

type AVLTreeNode struct {
	key   DataType
	high  int
	left  *AVLTreeNode
	right *AVLTreeNode
}

func main() {
	data := []DataType{3, 2, 1, 4, 5, 6, 7, 16, 15, 14, 13, 12, 11, 10, 8, 9}
	fmt.Println(data)
	var root AVLTree = nil
	for _, value := range data {
		root = avl_insert(root, value)
		fmt.Println(" root -> key: ", root.key, "high :", root.high, "left", root.left, "right: ", root.right)
	  //  preorder(root)
	}
	preorder(root)
	fmt.Println()
	midorder(root)
	fmt.Println()
}


func highTree(p AVLTree) int {
	if p == nil {
		return -1
	} else {
		return p.high
	}
}

func max(a, b int) int {
	if a > b {
		return a
	} else {
		return b
	}
}

/*Please look LL*/
func left_left_rotation(k AVLTree) AVLTree {
	var kl AVLTree
	kl = k.left
	k.left = kl.right
	kl.right = k
	k.high = max(highTree(k.left), highTree(k.right)) + 1
	kl.high = max(highTree(kl.left), k.high) + 1
	return kl
}

/*Please look RR*/
func right_right_rotation(k AVLTree) AVLTree {
	var kr AVLTree
	kr = k.right
	k.right = kr.left
	kr.left = k
	k.high = max(highTree(k.left), highTree(k.right)) + 1
	kr.high = max(k.high, highTree(kr.right)) + 1
	return kr
}

/*so easy*/
func left_righ_rotation(k AVLTree) AVLTree {
	k.left = right_right_rotation(k.left)
	return left_left_rotation(k)
}

func right_left_rotation(k AVLTree) AVLTree {
	k.right = left_left_rotation(k.right)
	return right_right_rotation(k)
}

func avl_insert(avl AVLTree, key DataType) AVLTree {
	if avl == nil {
		avl = new(AVLTreeNode)
		if avl == nil {
			fmt.Println("avl tree create error!")
			return nil
		}else {
			avl.key = key
			avl.high = 0
			avl.left = nil
			avl.right = nil
		}
	} else if key < avl.key {
		avl.left = avl_insert(avl.left, key)
		if highTree(avl.left)-highTree(avl.right) == 2 {
			if key < avl.left.key { //LL
				avl = left_left_rotation(avl)
			} else { // LR
				avl = left_righ_rotation(avl)
			}
		}
	} else if key > avl.key {
		avl.right = avl_insert(avl.right, key)
		if (highTree(avl.right) - highTree(avl.left)) == 2 {
			if key < avl.right.key { // RL
				avl = right_left_rotation(avl)
			} else {
				fmt.Println("right right", key)
				avl = right_right_rotation(avl)
			}
		}
	} else if key == avl.key {
		fmt.Println("the key", key, "has existed!")
	}
	//notice: update high(may be this insert no rotation, so you should update high)
	avl.high = max(highTree(avl.left), highTree(avl.right)) + 1
	return avl
}

func preorder(avl AVLTree) {
	if avl != nil {
		fmt.Print(avl.key, "\t")
		preorder(avl.left)
		preorder(avl.right)
	}
}

func midorder(avl AVLTree) {
	if avl != nil {
		midorder(avl.left)
		fmt.Print(avl.key, "\t")
		midorder(avl.right)
	}
}

/*display avl tree*/
func display(avl AVLTree) {

}



go语言:实现avl 树(附完整源码) 阅读详情

相关推荐

Go-Sparkzstd-用golang编写的zstd解压缩程序

Sparkzstd - 用golang编写的zstd解压缩程序

Spark初识

Spark的背景、定义、特点 背景 MapReduce框架局限性 仅支持Map和Reduce两种操作,提供给用户的只有这两种操作 编程复杂度略高,学习和使用成本略高。 处理效率低效 Map中间结果写磁盘,Reduce写HDFS,多个MR之间通过HDFS交换数据 任务调度和启动开销大 在机器学习、图计算等方面支持有限,性能效率表现比较差。 mapreduce的机器学习框架,称为mahout。 定义 专为大规模数据处理而设计的快速通用的计

qq_57011804的博客 2620

光伏逆变器在环测试解决方案

光伏行业是利用太阳能光辐射将其转化为可用电能的行业。近年来,为应对气候变化和能源安全等挑战,全球对清洁能源的需求不断增长。太阳能作为最具潜力和可再生的能源之一,被视为替代传统化石能源的重要选择,光伏行业因此得到了迅猛发展,并在全球范围内得到了广泛应用。许多国家和地区都将光伏技术作为关键的能源发展方向。尤其是在新兴和发展中国家,光伏发电具有巨大的增长潜力,将成为未来市场竞争的重点。随着规模化生产的推进,光伏组件的制造成本不断降低。

shiwei0813的博客 959

golang能做大数据开发吗?主流的开发框架有哪些?

一种快速的大规模数据处理框架,支持批处理和流式数据处理,可以使用 Golang 编写 Spark 应用程序。Golang 在大数据领域的应用越来越广泛,可以处理大规模的数据集,同时具有高并发,低延迟和高可用性等优点。:一种分布式的流式数据处理框架,具有低延迟和高吞吐量的特点,支持包括 Golang 在内的多种编程语言。:一种开源的容器编排系统,可以管理和调度大规模的容器化应用程序,同时也支持 Golang 开发。:一种流式数据处理框架,可以处理批处理数据和流式数据,支持多种计算引擎和数据存储系统。

学亮编程手记 2675

Penpot自托管全攻略:5分钟搞定私有化部署(附Docker配置详解)

本文详细介绍了Penpot开源原型设计工具的私有化部署全流程,从Docker基础配置到企业级优化方案。通过分步指南和实战技巧,帮助设计团队快速搭建安全高效的自托管环境,实现数据自主可控。内容涵盖LDAP集成、性能监控、备份策略等关键企业需求,是Penpot私有化部署的完整参考手册。

sugar的博客 1132

手把手教你用EG2153搭建开关电源:SOP-8封装驱动芯片的5个设计技巧

本文详细介绍了使用EG2153自振荡半桥驱动芯片搭建开关电源的五个核心设计技巧。内容涵盖从深入理解芯片工作机制、频率编程计算误区、SOP-8封装的热管理方案,到死区时间评估与外部保护电路设计,以及实战调试与故障排查指南,旨在帮助工程师实现稳定可靠的小功率电源设计。

weixin_29200485的博客 378

2024年Go最全Go异常处理——defer、panic、recover,Golang零基础

事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!二、panic和recover(宕机和宕机恢复)

2401_84920027的博客 1316

Python自动化测试全套教程-第一天(python、pycharm开发环境的安装与配置(图文超级详细);附安装包)

本文介绍了Python开发环境的完整安装配置流程。主要内容包括:1) Python解释器的下载安装与版本检测方法;2) PyCharm IDE的下载安装步骤,包括专业版和社区版的选择;3) PyCharm的基础配置和项目创建方法;4) 开发环境的基本构造说明。文章提供了两种获取安装包的方式(官网下载和文章附件),并详细说明了解释器卸载、安装过程中的注意事项,以及如何验证环境配置成功。特别强调了PyCharm安装时的路径选择和虚拟环境的创建方法,为Python初学者提供了完整的开发环境搭建指南。

kiwi_king的博客 2035

Apache Spark Connect Go 项目常见问题解决方案

Apache Spark Connect Go 项目常见问题解决方案 项目基础介绍 Apache Spark Connect Go 是一个实验性的客户端项目,旨在为 Apache Spark 提供一个用 Golang 编写的连接客户端。该项目目前处于高度实验阶段,不建议在生产环境中使用。Apache Spark 是一个开源的分布式计算系统,广泛用于大数据处理和分析。Spark Connect Go...

gitblog_00832的博客 463

【PostgreSQL】PostgreSQL数据库函数比对模板(PG通用)

LOOKUP 函数从单行或单列区域 (区域:工作表上的两个或多个单元格。区域中的单元格可以相邻或不相邻。)或数组 (数组:用于建立可生成多个结果或可对在行和列中排列的一组参数进行运算的单个公式。数组区域共用一个公式;数组常量是用作参数的一组常量。LOOKUP 函数具有两种语法形式:向量形式和数组形式。vlookup查找匹配值超过255个字符显示#Value的解决办法。如果值为错误值 #N/A,则返回 TRUE。

tttzzzqqq2018的博客 1493

反光柱定位算法实战03:VEnus代码解析和纯反光柱定位中的可改进方向

本文深入解析了开源框架VEnus的反光柱定位与建图实现流程,包括强度提取、聚类、数据关联、位姿优化等核心模块。同时指出其三大局限:匹配质量脆弱性、单一传感器依赖和地图扩展逻辑缺失,并提出改进方向:融合里程计/IMU数据、引入图优化后端、建立动态地图维护机制。该分析为基于反光柱的定位系统优化提供了实用参考,有助于提升工业场景下的定位鲁棒性和精确性。

Studying…… 520

2024年最新【算法学习】剑指 Offer 64(2),2024年最新vue总结来了

--### c// 2的14次正好超过10000// 等差数列求和公式n * (n + 1) / 2public:// 2的14次正好超过10000// 等差数列求和公式n * (n + 1) / 2# 2的14次正好超过10000# 等差数列求和公式n * (n + 1) / 2ans = 0a = nb = n + 1// 2的14次正好超过10000// 等差数列求和公式n * (n + 1) / 2ans += a。

2401_84910839的博客 593

FX5U PLC运动控制库安装(PLCopen Motion Control FB参考)

下面我们介绍三菱FX5U PLC的运动控制库PLCopen Motion Control FB的安装。

RXXW_Dor的博客 1524

golang实现AVL树算法 【AVL树】【算法】【golang】

golang avl树算法 package main import ( "fmt" ) var nodeCnt int type Node struct { val int left, right *Node h int } func max(i, j int) int { if i > j { return i } return j } func min(i, j int) int { if i < j { return i

LYR 的博客 662

mapbox进阶,dem数据转为等高面,加载转换后的等高面到地图

本文详细介绍如何基于mapbox-gl v3.*.* 版本,使用dem数据转为等高面,加载转换后的等高面到地图,亲测可用。希望能帮助到您。一起学习,加油!加油!

我哎GIS博客 407

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

【数据结构 -- AVL树】c语言和go语言实现

本文讲述了AVL的性质、实现思想及代码实现,更正了代码实现部分,使用 C 语言和 Go 语言实现AVL树

2401_87046050的博客 1532

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

(22)Go实现AVL树-实现和测试

继上一篇 《(21)Go实现AVL树-算法解析》 的后续 https://www.jianshu.com/p/943243f5ee1e AVL树的定义和实现 type node struct { key int value int height int left *node right *node } type avlTree struct { size int Ro...

哥斯拉啊啊啊哦的博客 393

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

golang实现AVL树

AVL树是带有平衡条件的二叉查找树 特点:AVL树中每个节点的左子树和右子树的高度最多差1   旋转:由于插入操作可能会破坏AVL树的平衡特性,故在插入完成之前通过对树进行简单修正来恢复平衡 示例代码如下: package main import ( "fmt" ) type avlTreeNode struct { key int high int

skh2015java的博客 1424

《零基础Go语言算法实战》【题目 5-6】用 Go 语言实现一棵 AVL 树

用Go语言实现一棵AVL树,注意不能使用Go语言内置函数。题目明确要实现AVL树,用Go语言实现AVL树即可。fmt.Println("\n插入了如下树")fmt.Println("\n删除了如下树")【题目5-6】用Go语言实现一棵AVL树。fmt.Println("空树")//向AVL树中插入一个节点。//从AVL树中删除单个节点。《零基础Go语言算法实战》②Go语言实现。

shirdon-廖显东的博客 347

(21)Go实现AVL树-算法解析

了解avltree树之前先了解几个概念 // 1)什么是二分搜索树; 2)什么是平衡树; 3)什么自平衡二分搜索树; 1)二分搜索树以及缺陷 // 如上图,是一颗二分搜索树,从添加查找节点,时间复杂度均为O(h),但在极端情况下, 如按顺序向一个空二分搜索树中添加0,1,2,3,4,二分搜索数会退化为单链,这时候时间 时间复杂度会变成O(n),如下图,为了避免这种情况需要结合平衡树做改进...

哥斯拉啊啊啊哦的博客 265

一种基于AVL树的Map实现(使用golang)

AVL树是以其发明者Adelson-Velskii和Landis命名的一种二叉查找树。均衡因子-1、0、1代表每个节点的均衡状态。为了更简单的实现,我们记录底板的高度并动态计算其平衡系数。向左旋转和向右旋转。对于向右旋转,假设我们有一棵以R为根节点的树,我们将整棵树右转90度,然后将其调整为有效的树。对于向左旋转,假设L是树的根节点,我们将整个树向左旋转90度,最后将其调整为有效的树。

学者的博客 306

Go版数据结构 -【4.3 AVL树】

AVL 树 是 二叉搜索树 的一个自平衡扩展,它通过旋转操作来保持树的平衡。 与普通的二叉搜索树不同,AVL 树在每次插入或删除节点时,都会检查树的平衡因子,并进行必要的调整以确保树的高度尽可能保持平衡。 本节我们将介绍AVL 树的基本概念、平衡因子、旋转操作,以及AVL 树的Go语言实现。

Swxctx 1282

Go语言算法和数据结构(十)AVL树

AVL树是一种自平衡二叉搜索树,通过维护节点平衡因子实现高效数据操作。摘要介绍了AVL树的核心实现:1)节点结构包含高度、值和左右子节点;2)关键操作包括旋转调整(左旋/右旋)、插入删除时的平衡维护;3)提供完整代码示例,展示节点插入、删除和遍历的实现。文章还介绍了两种实现方式:基础实现使用递归处理平衡,进阶实现通过方向标志优化旋转操作。最后演示了AVL树的基本使用,包括创建、插入和删除节点。该实现适用于需要频繁更新的有序数据场景。

不愿言弃-念何的博客 277

最全【算法学习】AVL平衡二叉搜索树原理及各项操作编程实现(C++,2024年最新干了5年Golang开发还没掌握binder机制

/更改原根节点的左子树。//更改原根节点左孩子的右子树。//左左外侧插入导致的不平衡,采用单旋转-右旋转进行修正。//右右外侧插入导致的不平衡,采用单旋转-左旋转进行修正。//对新产生的树进行一次单旋转-右旋转。//对新产生的树进行一次单旋转-左旋转。//对其左子树进行一次单旋转-左旋转。//对其右子树进行一次单旋转-右旋转。//得到树中的元素值最小的那个节点。//插入点位于T的左子结点的右子树。//插入点位于T的右子节点的左子树。//双旋转可以通过两次单旋转实现。//得到树中的元素值最大的节点。

2401_84920027的博客 1081

GOLANG实现的一个avl tree api

用golang实现了一个avl tree的api。 avlTree.go /* ** an avl tree api: //==&gt;&gt; operator tree api: //insert an x to AvlTree, invoker format: t = tree.Insert(t, x) func Insert(tree *AvlNode, x ElementType)...

weixin_30746129的博客 367

2024年Go最全平衡二叉树(AVL)_avl树全称是什么,带你一起探究Golang事件分发机制

增加高度属性二叉搜索树是否平衡,取决于左右子树的高度差插入节点或删除节点时,想要知道二叉树是否保持平衡,需要计算左右子树的高度计算左右子树的高度,一般通过自顶向下或自底向上的方式,递归计算(不对深度和高度加以区分)这样将会存在一定的时间开销和空间开销因此,需要在原有的TreeNode基础上,增加一个高度字段,用于记录当前节点的高度空节点的高度为0,叶子节点的高度为1,平衡二叉树,树节点的定义如下// 获取某个节点的高度。

2401_84925780的博客 610
上一篇: a simple erlang process pool analysis
下一篇: PoolBoy
laohan_
博客等级 码龄15年 112粉丝 224原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值