平衡二叉树(AVL树)

平衡二叉树:是一颗空树;或者具有以下性质的树:它的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值不超过1。

平衡二叉树的关键在于插入结点时如何保持整棵树的平衡性。

下面是不平衡发生的四种情况:

(1)平衡二叉树某一节点的左孩子的左子树上插入一个新的节点,使得该节点不再平衡。

LL型(左孩子的左子树)

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

/* return pointer to the new subtree root */
AVLNode *single_rotate_ll(AVLNode *node)	 //LL
{
	AVLNode *p = node->lchild;

	node->lchild = p->rchild;
	p->rchild = node;

	node->height = max(height(node->lchild), height(node->rchild)) + 1;
	p->height = max(height(p->lchild), height(p->rchild)) + 1;
	//p->height = max(height(p->lchild), node->height) + 1;

	return p;
}

(2) 平衡二叉树某一节点的右孩子的右子树上插入一个新的节点,使得该节点不再平衡。

RR型平衡旋转法(右孩子的右子树)

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

AVLNode *single_rotate_rr(AVLNode *node)	 //RR
{
	AVLNode *p = node->rchild;

	node->rchild = p->lchild;
	p->lchild = node;

	node->height = max(height(node->lchild), height(node->rchild)) + 1;
	p->height = max(height(p->lchild), height(p->rchild)) + 1;
	//p->height = max(node->height, height(p->rchild)) + 1;

	return p;
}

(3)平衡二叉树某一节点的左孩子的右子树上插入一个新的节点,使得该节点不再平衡。

LR型平衡旋转法(左孩子的右子树)

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

AVLNode *double_rotate_lr(AVLNode *node)	//LR
{
	node->lchild = single_rotate_rr(node->lchild);
	return single_rotate_ll(node);
}

(4) 平衡二叉树某一节点的右孩子的左子树上插入一个新的节点,使得该节点不再平衡。

RL型平衡旋转法(右孩子的左子树)

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

AVLNode *double_rotate_rl(AVLNode *node)	//RL
{
	node->rchild = single_rotate_ll(node->rchild);
	return single_rotate_rr(node);
}

AVl树的结构体为:

typedef struct AVLNode
{
	int data;
	int height;
	struct AVLNode *lchild, *rchild;
}AVLNode;

计算以node结点为根的树的高度:

int height(AVLNode *node)
{
	if (node == NULL)
		return -1;
	else
		return node->height;
}

现在可以写出avl树的插入代码了:

AVLNode *insert(AVLNode *root, int data)
{
	if (root == NULL)
	{
		root = (AVLNode*)malloc(sizeof(struct AVLNode));
		root->data = data;
		root->lchild = root->rchild = NULL;
		root->height = 0;
	}
	else if (data < root->data)
	{
		root->lchild = insert(root->lchild, data);
		if (height(root->lchild) - height(root->rchild) == 2)   //左子树高度-右子树高度
		{
			if (data < root->lchild->data)	//LL
				root = single_rotate_ll(root);
			else
				root = double_rotate_lr(root);     //LR
		}
	}
	else if (data > root->data)
	{
		root->rchild = insert(root->rchild, data);
		if (height(root->rchild) - height(root->lchild) == 2)	 //右子树高度-左子树高度
		{
			if (data < root->rchild->data)	//RL
				root = double_rotate_rl(root);
			else
				root = single_rotate_rr(root);	   //RR
		}
	}
	//else
	//{}  //data is in the tree already, do nothing

	root->height = max(height(root->lchild), height(root->rchild)) + 1;
	return root;
}

中序遍历avl树:

void inorder_traversal_tree(AVLNode *node)
{
	if (node != NULL)
	{
		inorder_traversal_tree(node->lchild);
		printf("%d ", node->data);
		inorder_traversal_tree(node->rchild);
	}
}

后续遍历以释放树的结点:

void destory_tree(AVLNode*node)
{
	if (node != NULL)
	{
		destory_tree(node->lchild);
		destory_tree(node->rchild);
		free(node), node = NULL;
	}
}

测试代码:

int main()
{
	int arr[] = {3, 2, 1, 4, 5, 6, 7, 16, 15, 14, 13, 12, 11, 10, 8, 9};
	AVLNode* T = NULL;
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
		T = insert(T, arr[i]);

	inorder_traversal_tree(T);
	destory_tree(T);
	getchar();
	return 0;
}

参考:AVL树的旋转

平衡二叉树 AVL 的插入节点后旋转方法分析

平衡二叉树(AVL树),布布扣,bubuko.com

时间: 2024-10-12 15:21:40

平衡二叉树(AVL树)的相关文章

图解平衡二叉树,AVL树(一)

图解平衡二叉树,AVL树(一) 学习过了二叉查找树,想必大家有遇到一个问题.例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建立的树如图2,才能够最大地体现二叉树的优点. 在上述的例子中,图2就是一棵平衡二叉树.科学家们提出平衡二叉树,就是为了让树的查找性能得到最大的体现(至少我是这样理解的,欢迎批评改正).下面进入今天的正题,平衡二叉树. AVL的定义 平衡二叉查找树:简称平衡二叉树.由前

平衡二叉树,AVL树之图解篇

学习过了二叉查找树,想必大家有遇到一个问题.例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建立的树如图2,才能够最大地体现二叉树的优点.            在上述的例子中,图2就是一棵平衡二叉树.科学家们提出平衡二叉树,就是为了让树的查找性能得到最大的体现(至少我是这样理解的,欢迎批评改正).下面进入今天的正题,平衡二叉树. AVL的定义 平衡二叉查找树:简称平衡二叉树.由前苏联的数学

算法学习笔记 平衡二叉树 AVL树

AVL树是最先发明的自平衡二叉查找树, 其增删查时间复杂度都是 O(logn), 是一种相当高效的数据结构.当面对需要频繁查找又经常增删这种情景时,AVL树就非常的适用.[ 博客地址:http://blog.csdn.net/thisinnocence ] AVL树定义 AVL树诞生于 1962 年,由 G.M. Adelson-Velsky 和 E.M. Landis 发明.AVL树首先是一种二叉查找树.二叉查找树是这么定义的,为空或具有以下性质: 若它的左子树不空,则左子树上所有的点的值均小

java数据结构与算法之平衡二叉树(AVL树)的设计与实现

[版权申明]未经博主同意,不允许转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53892797 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) java数据结构与算法之栈(Stack)设

图解:平衡二叉树,AVL树

学习过了二叉查找树,想必大家有遇到一个问题.例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建立的树如图2,才能够最大地体现二叉树的优点.            在上述的例子中,图2就是一棵平衡二叉树.科学家们提出平衡二叉树,就是为了让树的查找性能得到最大的体现(至少我是这样理解的,欢迎批评改正).下面进入今天的正题,平衡二叉树. AVL的定义 平衡二叉查找树:简称平衡二叉树.由前苏联的数学

平衡二叉树-AVL树的构建和操作

首先上一下单纯的二叉树插入节点的代码,用的是不返回新根节点的方式: 1 void insertNode(BTree *&root,int data) 2 { 3 if (root == nullptr)//当根节点为NULL时,在根节点上插入 4 { 5 root = initRoot(data); 6 return; 7 } 8 if (root->data == data)//当插入数据等于根节点时,不插入 9 { 10 return; 11 } 12 if (root->data

平衡二叉树,AVL树之代码篇

看完了第一篇博客,相信大家对于平衡二叉树的插入调整以及删除调整已经有了一定的了解,下面,我们开始介绍代码部分. 首先,再次提一下使用的结构定义 1 typedef char KeyType; //关键字 2 typedef struct MyRcdType //记录 3 { 4 KeyType key; 5 }RcdType,*RcdArr; 6 typedef enum MyBFStatus //为了方便平衡因子的赋值,这里进行枚举 7 { //RH,EH,LH分别表示右子树较高,左右子树等高

大话数据结构—平衡二叉树(AVL树)

平衡二叉树(Self-Balancing Binary Search Tree/Height-Balanced Binary Search Tree),是一种二叉排序树,其中每一个节点的左子树和右子树的高度差至多等于1. 平衡二叉树的前提是二叉排序树,不是二叉排序树的都不是平衡二叉树. 平衡因子BF(Balance Factor):二叉树上节点的左子树深度减去右子树深度的值. 最小不平衡子树:距离插入节点最近的,且平衡因子的绝对值大于1的节点为根的子树. 下图中,新插入节点37时,距离它最近的平

【数据结构】第9章 查找! (二叉搜索树BST AVL树 B-(+)树 字典树 HASH表)

难产的笔记...本来打算用1天 结果前前后后拖了5天 §9.1 静态查找表 9.1.1 顺序表的查找 各种扫 自己脑补吧 复杂度O(n) 9.1.2 有序表的查找 若表是单调的,则可以利用二分查找.复杂度O(logn) 9.1.3 静态树表的查找 见 http://blog.csdn.net/area_52/article/details/43795837 9.1.4 索引顺序表的查找 建立索引表查找 §9.2 动态查找表 动态查找表的特点是,表结构本身是在查找过程中动态生成的,即对于给定值ke

数据结构与算法系列----平衡二叉树(AVL树)

一:背景 平衡二叉树(又称AVL树)是二叉查找树的一个进化体,由于二叉查找树不是严格的O(logN),所以引入一个具有平衡概念的二叉树,它的查找速度是O(logN).所以在学习平衡二叉树之前,读者需要了解二叉查找树的实现,具体链接:二叉查找树 那么平衡是什么意思?我们要求对于一棵二叉查找树 ,它的每一个节点的左右子树高度之差不超过1.(对于树的高度的约定:空节点高度是0:叶子节点高度是1.)例如下图: 如果我们的二叉查找树是不平衡该怎么办?进行旋转.经过分析发现,出现不平衡无外乎四种情况,下面我