AVL树及C语言实现

AVL树(C语言实现) AVL树的相关操作,包括插入,删除,查找,调整。(C语言实现) 阅读详情

概念

 

平衡二叉树(Balanced binary tree)是由苏联数学家Adelson-Velskii and Landis于1962年首先提出的,所以又称为AVL树。

定义:平衡二叉树或为空树,或满足如下性质的二叉树:

 (1)本身首先是一棵二叉搜索树

  (2)左右子树深度之差的绝对值不超过1;

  (3)左右子树仍然为平衡二叉树.

平衡因子BF=左子树深度-右子树深度.

平衡二叉树每个结点的平衡因子只能是1,0,-1。若其绝对值超过1,则该二叉排序树就是不平衡的。
通过下面幅图可以看出,平衡二叉树可以保证最差查找效率为O(logN),而二叉查找树的最差查找效率为O(N)。

 

插入节点的调整方法

 

若向平衡二叉树中插入一个节点后破坏了平衡二叉树的平衡性,首先从根节点到该新插入节点的路径之逆向根节点方向找到第一个失去平衡的节点,然后以该失衡节点和它相邻的刚查找过的两个节点构成调整子树,使之成为新的平衡子树。当失去平衡的最小子树被调整为平衡子树后,原来其他所有不平衡子树无需调整,整个二叉排序树就又成了一个平衡二叉树。

失去平衡的最小子树是指以离插入节点最近,且平衡因子绝对值大于1的节点作为根的子树。

 (1)LL型平衡旋转法
由于在A的左孩子B的左子树上插入结点F,使A的平衡因子由1增至2而失去平衡。故需进行一次顺时针旋转操作。 即将A的左孩子B向右上旋转代替A作为根结点,A向右下旋转成为B的右子树的根结点。而原来B的右子树则变成A的左子树。

(2)RR型平衡旋转法
由于在A的右孩子C 的右子树上插入结点F,使A的平衡因子由-1减至-2而失去平衡。故需进行一次逆时针旋转操作。即将A的右孩子C向左上旋转代替A作为根结点,A向左下旋转成为C的左子树的根结点。而原来C的左子树则变成A的右子树。

(3)LR型平衡旋转法
由于在A的左孩子B的右子数上插入结点F,使A的平衡因子由1增至2而失去平衡。故需进行两次旋转操作(先逆时针,后顺时针)。即先将A结点的左孩子B的右子树的根结点D向左上旋转提升到B结点的位置,然后再把该D结点向右上旋转提升到A结点的位置。即先使之成为LL型,再按LL型处理。

如图中所示,即先将圆圈部分先调整为平衡树,然后将其以根结点接到A的左子树上,此时成为LL型,再按LL型处理成平衡型。

(4)RL型平衡旋转法 

由于在A的右孩子C的左子树上插入结点F,使A的平衡因子由-1减至-2而失去平衡。故需进行两次旋转操作(先顺时针,后逆时针),即先将A结点的右孩子C的左子树的根结点D向右上旋转提升到C结点的位置,然后再把该D结点向左上旋转提升到A结点的位置。即先使之成为RR型,再按RR型处理。

如图中所示,即先将圆圈部分先调整为平衡树,然后将其以根结点接到A的左子树上,此时成为RR型,再按RR型处理成平衡型。

平衡化靠的是旋转。参与旋转的是3个节点(其中一个可能是外部节点NULL),旋转就是把这3个节点转个位置。注意的是,左旋的时候p->right一定不为空,右旋的时候p->left一定不为空,这是显而易见的。

如果从空树开始建立,并时刻保持平衡,那么不平衡只会发生在插入删除操作上,而不平衡的标志就是出现bf == 2或者 bf == -2的节点。

 

删除节点的调整方法

在平衡二叉树上删除节点x(假定有且仅有一个节点等于x)的过程如下:

1、采用二叉排序树的删除方法找到节点x并删除之;

2、沿着根到被删除节点的路线之逆逐层向上查找,必要时修改x祖先节点的平衡因子,因为删除后会使得某些子树的高度降低;

3、查找途中,一旦发现x的某个祖先*p失衡,就要进行调整。不妨设x节点在*p的左子树中,在*p节点失衡后,要做何种调整,取决于*p节点的右孩子,*p1,若*p1的平衡因子是1,则做RL调整;若*p1的平衡因子是-1,则做RR调整;若*p1的平衡因子是0,则做RL或者RR调整均可。如果x在*p右子树中,调整过程类似。

4、如果调整后,子树的高度降低了,这个过程还要继续,直到根节点为止。即,删除一个节点可能会引起多次调整,而不是插入时的至多一次调整。

 

 节点查找

 

和二叉排序树完全相同。

 

C语言实现一

由于没有删除某一个节点的功能,故在数据结构的定义中没有提供父节点指针。

#include <stdio.h>
#include <malloc.h>

typedef enum
{
	EH = 0,
	LH = 1,
	RH = -1	
}bh_t;


typedef enum
{
	FALSE = 0,
	TRUE = 1
}bool_t;

typedef int ElemType;

typedef struct BSTNode
{
	ElemType key;
	int bf;
	struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;


void InOrderTraverse(BSTree root)
{
	if(NULL != root)
	{
		InOrderTraverse(root->lchild);
		printf("%d\t",root->key);
		InOrderTraverse(root->rchild);
	}
}


void PreOrderTraverse(BSTree root)
{
	if(NULL != root)
	{
		printf("%d\t",root->key);
		PreOrderTraverse(root->lchild);
		PreOrderTraverse(root->rchild);
	}
}


void R_Rotate(BSTree *p)
{
	BSTree lc=(*p)->lchild;
	(*p)->lchild=lc->rchild;
	lc->rchild=*p;
	*p=lc;
}


void L_Rotate(BSTree *p)
{
	BSTree rc=(*p)->rchild;
	(*p)->rchild=rc->lchild;
	rc->lchild=*p;
	*p=rc;
}


void LeftBalance(BSTree *T)
{
	BSTree lc=(*T)->lchild;
	BSTree rd = lc->rchild;
	switch(lc->bf)
	{
		case LH:
			(*T)->bf=lc->bf=EH;
			R_Rotate(T);
			break;
		case RH:
			switch(rd->bf)
			{
				case LH: 
					(*T)->bf=RH;
					lc->bf=EH;
					break;
				case EH:
					(*T)->bf=lc->bf=EH;
					break;
				case RH:
					(*T)->bf=EH;
					lc->bf=LH;
					break;
			}
			rd->bf=EH;
			L_Rotate(&((*T)->lchild));
			R_Rotate(T);
			break;
	}
}


void RightBalance(BSTree *T)
{
	BSTree rc=(*T)->rchild;
	BSTree ld=rc->lchild;
	switch(rc->bf)
	{
		case RH:
			(*T)->bf=rc->bf=EH;
			L_Rotate(T);
			break;
		case LH:
			switch(ld->bf)
			{
				case RH:
					(*T)->bf=LH;
					rc->bf=EH;
					break;
				case EH:
					(*T)->bf=rc->bf=EH;
					break;
				case LH:
					(*T)->bf=EH;
					rc->bf=RH;
					break;
			}
			ld->bf=EH;
			R_Rotate(&((*T)->rchild));
			L_Rotate(T);
			break;
	}
}


bool_t InsertAVL(BSTree *t,ElemType e,bool_t *taller)
{
	if(NULL == t)
		return FALSE;
	if(NULL == *t)
	{
		*t=(BSTree)malloc(sizeof(BSTNode));
		if(NULL == *t)
			return FALSE;
		(*t)->key=e;
		(*t)->lchild=(*t)->rchild=NULL;
		(*t)->bf=EH;
		*taller=TRUE;
	}
	else
	{
		if(e==(*t)->key)
		{
			*taller=FALSE;
			return FALSE;
		}
		if(e<(*t)->key)
		{
			if(FALSE == InsertAVL(&((*t)->lchild),e,taller))
				return FALSE; 
			if(*taller)
			{
				switch((*t)->bf)
				{
					case LH:
						LeftBalance(t);
						*taller=FALSE;
						break;
					case EH:
						(*t)->bf=LH;
						*taller=TRUE;
						break;
					case RH:
						(*t)->bf=EH;
						*taller=FALSE;
						break;
				}
			}
		}
		else
		{
			if(FALSE == InsertAVL(&((*t)->rchild),e,taller))
				return FALSE; 
			if(*taller)
			{
				switch((*t)->bf)
				{
					case RH:
						RightBalance(t);
						*taller=FALSE;
						break;
					case EH:
						(*t)->bf=RH;
						*taller=TRUE;
						break;
					case LH:
						(*t)->bf=EH;
						*taller=FALSE;
						break;
				}
			}
		}
	}
	return TRUE;
}


BSTree searchAVL(BSTree t,ElemType key)
{
	BSTree p=t;
	while(p)
	{
		if(p->key==key)
			return p;
		else if(p->key<key)
			p=p->rchild;
		else
			p=p->lchild;
	}
	return p;
}

static void destroy(BSTree *t)
{
	if(NULL != *t)
	{
		destroy(&((*t)->lchild));
		destroy(&((*t)->rchild));
		free(*t);
		*t = NULL;
	}
	return;
}
void destroyAVL(BSTree root)
{
	if(NULL != root)
	{
		destroy(&root);
	}
	return;
}

int main(int argc,char *argv[])
{
	BSTree root=NULL,r;
	bool_t taller=FALSE;
	int array[]={13,24,37,90,53};
	int i = 0;
	for(i=0;i<5;i++)
		InsertAVL(&root,array[i],&taller);
	printf("inorder traverse\n");
	InOrderTraverse(root);

	printf("\npreorder traverse\n");
	PreOrderTraverse(root);

	printf("\nsearch key\n");
	r=searchAVL(root,37);
	if(r)
	{
		printf("%d\n",r->key);
	}
	else
	{
		printf("not find!\n");
	}
	destroyAVL(root);
	root = NULL;
}


 

Avl树的基本操作(c语言实现) #include #include typedef struct AvlNode *Position; typedef struct AvlNode *AvlTree; typedef int ElementType; struct AvlNode{ ElementType Element; AvlTree Left; AvlTree Right; int Height; }AvlNo 阅读详情

相关推荐

AVL树C语言完整实现

AVL树的介绍见http://blog.youkuaiyun.com/pngynghay/article/details/22443525,本文给出的是AVL树的一种实现。 采用非递归方式,效率较好,经过常规测试。   #include #include #include #include #include typedef enum { EH = 0, LH = 1, RH = -1

IT_Linux 2420

C语言-AVL树

当插入节点在“外侧”时(即左-左或右-右的情况),进行所谓的单旋转操作。在保留二叉搜索树特性的同时,又加上了平衡条件,即每个节点的左右子树的高度最多差1。《数据结构与算法分析》一书中认为AVL树的删除操作较为复杂,更加推荐使用懒惰删除,即保留节点在树中,但是加以标记。不过值得注意的是,代码中的Height函数单独出来写是有必要的,因为我们要处理空树的情况。总体上插入函数的思路与二叉搜索树的插入函数思路相似,不过多了对树高导致不平衡的条件的讨论。在有了以上对旋转的讨论之后,完成节点的插入操作就不再是难事。

2301_79349959的博客 1162

USB2.0基础知识总结

目录 1、协议层: 1.1、域分类 1.2 、USB传输方式: 1、协议层: 域和包定义:包是一次传输的单位,每个包由多个域组成; USB中是按照LSB进行字节传输; 1.1、域分类 1.1.1: 同步域(SYNC field) 所有的包都开始于同步域,在低速和全速通信中SYNC field用7个0和1个1来表示。 由于USB2.0使用了NRZI编码(0用翻转来表示,1用不翻转表示),所以00000001就是上图那样。 ...

qq_32938605的博客 4408

avl树的C语言实现(图解+注释)

【代码】avl树的C语言实现(图解+注释)

caradm的博客 194

可信数据空间关键技术和功能架构研究

可信数据空间(TDS)是实现数据安全共享的基础设施,通过数字合约和使用控制技术确保数据跨域流通的可信与安全。其架构包括服务平台和接入连接器,关键技术涵盖访问控制、隐私计算、区块链等。评估重点在于合规性、连接器能力、互联互通及安全体系。核心在于构建规则引擎而非简单数据汇聚,连接器开发比平台建设更重要。当前面临技术成本博弈、跨域身份互认等挑战,需平衡安全、性能与成本,推动数据要素市场发展。

逸尘的专栏 2222

深入理解光流法外推雷达回波

背景介绍 鉴于本人实在太过疲惫和劳累,一些简单的便于理解的废话就不在记录,耗费两天时间研究了一下光流法,本帖用于记录学习过程中源码的难点细节。 使用光流预测的核心有两个利用多张连续回波图像(变分)或者相邻两张回波图(交叉相关,LK等)计算出光流场(速度矢量场),之后利用半拉格朗日方法进行外推。 半拉格朗日方法 三时间步半拉格朗日方法,其核心公式如下 但这个有点难理解,但看一维的图就很好理解 它的核心就是迭代求Am(位移矢量),如果理解困难的话,其实质上就是通过未来迭代(猜)出当前时刻的Am找到过去的假设

weixin_44695861的博客 6031

平衡二叉排序树之AVL树(C语言实现)

本文详细介绍了平衡二叉排序树中的AVL树,对失衡类型和不同失衡类型的调整方式做了细致的描写,并用C语言实现了AVL树

zhao_Tao_WA的博客 1155

[附源码]计算机毕业设计Python财务管理系统(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程项目运行环境配置:Pychram社区版+py项目技术:django + python+ Vue 等等组成,B/S模式 +pychram管理等等。环境需要1.运行环境:最好是python3.7.7,我们在这个版本上开发的。其他版本理论上也可以。2.pycharm环境:pycharm都可以。推荐pycharm社区版;3.mysql环境:建议是用5.7版本均可。

巧灵计算机程序设计 1067

C 语言实现 AVL 树

一、平衡二叉树简介     平衡二叉树又称 AVL树,其具有如下两个性质: 必须是二叉树; 必须是一颗空树或者其左右子树的高度只差不超过 1。     平衡二叉树的实现主要是为了避免普通二叉查找树在极端情况下(全部节点只有左孩子或者全部节点只有右孩子)会像链表那样影响性能。 二、AVL树 自平衡 #include <stdio.h> #include <stdlib.h> #include <string.h> #include "AVLTree.h" #defi

SauryN的博客 2523

基石篇:多模态数据工程导论与核心概念

多模态数据工程不是写Python脚本处理几张图片,而是设计并构建一套系统,来规模化地生产高质量、可追溯、符合合规要求的模型就绪数据。本文将为你建立正确的数据工程思维框架,明确其在多模态AI生态中的战略地位,并为后续的深入学习奠定坚实基础。

jiaquan3011的博客 628

YOLO模型从10MB瘦到2MB!剪枝+INT8量化双方案(精度损失<1%,附部署代码)

摘要:本文介绍了一种针对边缘设备的YOLO模型轻量化方案,通过"结构化剪枝+INT8量化"组合技术,将YOLOv8n模型从6.4MB压缩至2MB,体积减少68.75%,推理速度提升80%,同时保持精度损失小于1%。文章详细讲解了剪枝工具选择、通道剪枝实现、量化校准等关键步骤,并提供了完整的代码示例。特别强调了剪枝保留率、校准集使用、微调必要性等实践要点,帮助开发者在树莓派等资源受限设备上实现高效目标检测。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 756

C语言 平衡二叉搜索树(AVL树)

AVL树是一种自平衡的二叉搜索树,它在插入和删除操作后能够通过旋转操作来保持树的平衡。AVL树是由苏联数学家G.M. Adelson-Velsky和E.M. Landis于1962年提出的,其名称即来源于他们的姓氏的首字母。

m0_73070900的博客 529

【学术情报智库】目录学的数字化蜕变:从古籍整理到AI知识图谱的跨越

我们既是浩瀚知识的守望者,也是数字智识的开拓者。目录学数字化不是技术替代传统,而是融合创新,让学术的系统性与多样性在新媒介下焕发新的生命。以AI为桥,既要智能链接,也要人文关照——这是对自我文明的深情回应,也是新知时代的庄严约定。

高校图书馆高级系统架构师/研究馆员,推动高校AI从概念演示到可评审、可交付、可运维:路线图与立项评审、PoC交付、评测回归与上线运维(Baseline/Eval/Ops)。 1420

用C语言实现的——一个完整的AVL树的交互式系统

用C语言实现的——一个完整的AVL树的交互式系统,支持查找、插入、删除、查找指定节点的前驱和后继节点、树形展示、层次展示、文件存储等功能。

2401_84643729的博客 1664

喷涂机器人系列编程:ABB IRB 5500_(7).喷涂质量控制与优化

通过编程手段对ABB IRB 5500喷涂机器人进行质量控制和优化,可以显著提高喷涂的均匀性和附着力,减少涂层缺陷。具体的方法包括喷涂参数的调整、路径规划的优化、喷涂效果的检测与反馈,以及喷涂参数的动态调整。综合评估系统可以进一步确保喷涂质量的稳定性和一致性,帮助汽车制造企业提高产品质量和生产效率。

zhubeibei168的博客 851

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

AVL树实现(C语言)

这段代码实现了AVL树的基本操作,包括插入、查找、中序遍历和销毁。每行代码都有注释,解释了代码的作用。这个实现假设树中没有重复的值。在实际应用中,可能需要处理重复值和其他边界情况。自旋原理是指在插入或删除操作后,AVL树通过一系列的旋转操作来恢复树的平衡。以下是AVL树的C语言实现,包括插入、删除、遍历、查找和销毁功能,每行代码都有注释。

qq_40844444的博客 443

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

AVL树的实现(C语言实现)

最近恶补数据结构,不过抱着小侄女实在复习不进去。。。这才复习完树 当时对于平衡树就没有一个系统的了解  具体的感念就不贴了,仔细说一说如何调整平衡二叉树 如果插入破坏了原有的平衡,“麻烦结点”在发现者右子树的右边,因而叫 RR 插入,需要RR 旋转(右单旋) 做如下调整 “麻烦结点”在发现者左子树的左边,因而叫 LL 插入,需要LL 旋转(左单旋)

rainxbow的专栏 1061

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

AVL树详解及其C语言实现

本文讲述AVL树、应用场景及其C语言实现。AVL树的全称是Adelson-Velsky and Landis Tree,简称AVL树。AVL树是一种自平衡的二叉搜索树,其特点是在每次插入或删除操作之后,都会自动调整树的结构,以确保树的高度保持在尽可能小的状态。这种调整是通过旋转操作来实现的,以保持树的平衡性。在AVL树中,每个节点都维护了一个平衡因子,即其左子树的高度减去右子树的高度。平衡因子的值只能为-1、0或1。

SEU123WW的博客 737

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

概要 本章介绍AVL树。和前面介绍"二叉查找树"的流程一样,本章先对AVL树的理论知识进行简单介绍,然后给出C语言的实现。本篇实现的二叉查找树是C语言版的,后面章节再分别给出C++和Java版本的实现。 建议:若您对"二叉查找树"不熟悉,建议先学完"二叉查找树"再来学习AVL树。 目录 1. AVL树的介绍 2. AVL树的C实现 3. AVL树的C实现(完整源码) 4. AVL树的

ProgrammingRing的专栏 9440

AVL树C语言的实现

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

个人公众号: 码小菜 675

c 编程语言 树,使用C编程语言实现AVL树

本文将介绍AVL树及其插入、删除操作,最后使用C编程语言实现基于平衡因子(balance factor)的AVL树。什么是AVL树?AVL树(AVL tree)是前苏联计算机科学家Adelson-Velsky和Landis发明的一种自平衡二叉查找树(self-balancing binary search tree)。它有两大属性,一个是继承自二叉查找树的查找属性(binary search pr...

weixin_35715235的博客 226

用C语言实现一个AVL树

AVL树是一种平衡二叉树,它的每个节点的左右子树的高度相差不超过1。这个性质使得AVL树插入和删除操作的时间复杂度能够保持在对数级别,这与二叉搜索树相比具有较高的效率。 下面是一个用C语言实现AVL树的示例代码: ``` #include <stdio.h> #include <stdlib.h> typedef struct AVLTreeNode { int key...

weixin_35755823的博客 206

数据结构之 AVL树(平衡二叉树)(C语言实现)

AVL树(平衡二叉树)1. AVL树定义和性质AVL(Adelson-Velskii和Landis发明者的首字母)树时带有平衡条件的二叉查找树。二叉查找树的性能分析: 在一颗左右子树高度平衡情况下,最优的时间复杂度为O(log2nlog_2{n}),这与这半查找相同; 在一个只有右子树的二叉树中,最差的时间复杂度会脱变为线性查找O(n)。 二叉查找树的实现:二叉查找树的C语言实现由于二叉查找树存在以

men_wen的博客 5445

AVL树C语言实现

AVL树介绍 AVL树是带有平衡条件的二叉查找树。这个平衡条件必须容易保持,而且它必须保证树的高度是O(logN)。AVL树其每个节点的左子树和右子树高度最多差1(空树的高度为-1),每个节点保留其高度信息。下图中,左边的图是AVL树,而右边的不是。 节点插入 当对一个AVL树插入节点后,只有那些从插入节点到根节点的路径上的节点的平衡可能被改变,因为这些节点的子树可能发生变化。当我们

UniversityCD的专栏 2083

AVL树--C语言实现

/************************************************************************ *                        AVL树 demo程序                                  * Version:1.0    实现insert函数                             

nizqsut的专栏 353
上一篇: hash算法原理及常见函数
下一篇: AVL树C语言完整实现
IT_Linux
博客等级 码龄14年 31粉丝 77原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值