数据结构-----平衡二叉树

这篇具有很好参考价值的文章主要介绍了数据结构-----平衡二叉树。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 目录

前言

1.平衡二叉树

1.1概念与特点

1.2与二叉排序树比较

1.3判断平衡二叉树

2.平衡二叉树的构建

2.1平衡因子 BF

2.2 LL型失衡(右旋)

2.3 RR型失衡(左旋)

2.4 LR型失衡(先左旋再右旋)

 2.5 RL型失衡(先右旋再左旋)

2.6构建平衡二叉树代码实现

 3.删除节点操作

3.1删除叶子节点

3.2删除只有一个左(右)子树的节点

3.3删除有左右子树的节点

3.4删除节点代码实现

4.平衡二叉树相关操作

4.1查找数据

4.2判断是否为平衡二叉树

4.3中序遍历输出

4.4销毁平衡二叉树


前言

        前面我发布了一篇介绍二叉排序树的相关文章,那么今天我们学习一种新的树----平衡二叉树,在此之前我们要学习过二叉排序树,才能更好的去学习平衡二叉树,平衡二叉树是二叉排序树的进一步优化,下面就一起来看看吧!

1.平衡二叉树

1.1概念与特点

        在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。

二叉排序树相关链接:数据结构-----二叉排序树_Gretel Tade的博客-CSDN博客 

 特性:

  • 平衡二叉树是一个二叉排序树
  • 它的左子树和右子树都是平衡二叉树
  • 左右子树高度之差(简称平衡因子)的绝对值不超过 1(即:-1,0,1)

 如图所示:平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

1.2与二叉排序树比较

在此之前我们学习过了二叉排序树的相关知识点,二叉排序树又名为二叉搜索树,但是当一个二叉排序树的形态是一个链状的话,那么搜索效率跟一个链表的搜索效率是毫无区别的,但是如果是一个平衡二叉树就不同了,因为平衡二叉树规定了左右子树高度差不会大于1,这样就可以大大提高了搜索的效率,下面看比较:

平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

当前我插入[1,2,3,4,5,6] 这一数组构建一个二叉排序树的时候,其形态是如下图所示,很明显是一个链态的,无异于一个链表,当我要去搜索数字6的时候,就要遍历到最后一个数字,搜索效率为 O(n)。 

平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

但是如果我通过构建平衡二叉树来储存这些数据的话,那就会有很大的不同,如下图所示,当我要去搜索最后一个节点的时候,就不需要去遍历这么多节点了,可以这么说,平衡二叉树是排序二叉树的优化结果。

平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

1.3判断平衡二叉树

  • 1. 是二叉排序树
  • 2. 任何一个节点的左子树或者右子树都是平衡二叉树,而且左右高度差小于等于 1

(1)这个不是平衡二叉树, 因为右子树比左子树高度差大于2

平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

(2)这个不是平衡二叉树,因为没有符合二叉排序树的要求

平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

(3)这个是平衡二叉树,既满足二叉排序树的要求,而且左右子树高度差小于2.

平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

2.平衡二叉树的构建

        前面去构建一个二叉排序树,非常简单,只需要排序就行了,那构建一个平衡二叉树不仅仅要考虑到排序问题,还要考虑到左右子树高度不大于1才行,下面我介绍一种通过旋转的方法来去构建平衡二叉树。

2.1平衡因子 BF

定义:左子树和右子树高度差

计算方法:左子树高度减右子树高度的绝对值

 当满足BF<=1的时候,这个树就满足平衡条件。当不满足平衡条件的话,那就只能去通过旋转来实现平衡。下面有4种不满足平衡条件的情况,如图所示:

平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

 树1是满足平衡条件的情况;

树2是在左子树右子节点出现失衡情况,属于 LR型

树3是在右子树右子节点出现失衡情况,属于 RR型

树4是在左子树左子节点出现失衡情况,属于 LL型

树5是在右子树左子节点出现失衡情况,属于 LR型

下面我就一一讲解怎么去通过旋转来处理上面这四种失衡问题。

2.2 LL型失衡(右旋)

 右旋就是通过顺时针旋转来实现平衡,就是处于右边的根结点落下变为叶子节点,而中间的节点变为新的根节点,最左边的叶子节点保持不变,最后形成新的结构。

动图演示:平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

2.3 RR型失衡(左旋)

对于RR型失衡,通过逆时针旋转,最左边的根结点落下,变成叶子节点,中间的节点变为新的根节点,最右边的叶子节点保持不变。

动图演示:平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

2.4 LR型失衡(先左旋再右旋)

对于LR型失衡,先在根节点左子树进行左旋处理,变成LL型失衡,然后再去通过右旋来实现整体平衡。动图演示如下:

 先左旋:

平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

再右旋: 

平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

 2.5 RL型失衡(先右旋再左旋)

对于RL型失衡,在根节点的右子树先进行右旋处理,形成RR型失衡,然后整体进行左旋处理,最后达到平衡状态,动态演示如下:

先右旋: 

平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树 再左旋:平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

2.6构建平衡二叉树代码实现

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int	Datatype;
typedef struct AVLtree {
	Datatype data;
	int heigh;//高度
	struct AVLtree* left;
	struct AVLtree* right;
}Node;

//绝对值
int abs(int a, int b) {
	return a - b > 0 ? a - b : b - a;
}

//创建一个节点
Node* Create_node(Datatype data) {
	Node* new_node = (Node*)malloc(sizeof(Node));
	if (!new_node) {
		printf("ERROR\n");
		exit(-1);
	}
	new_node->data = data;
	new_node->left = new_node->right = NULL;
	new_node->heigh = 0;
	return new_node;
}


//获取高度
int get_height(Node* T) {
	if (!T)
		return 0;
	else
		return T->heigh;
}


//1.插入右子树右节点,右旋
void right_rigth(Node** root) {
	Node* k = (*root)->right;
	(*root)->right = k->left;
	k->left = (*root);
	k->heigh = get_height(k->left) > get_height(k->right) ? get_height(k->left) : get_height(k->right);
	(*root)->heigh = get_height((*root)->left) > get_height((*root)->right) ? get_height((*root)->left) : get_height((*root)->right);
	*root = k;
}
//2.插入左子树左节点,失去平衡,左旋
void left_left(Node** root) {
	Node* k = (*root)->left;
	(*root)->left = k->right;
	k->right = (*root);
	k->heigh = get_height(k->left) > get_height(k->right) ? get_height(k->left) : get_height(k->right);
	(*root)->heigh = get_height((*root)->left) > get_height((*root)->right) ? get_height((*root)->left) : get_height((*root)->right);
	*root = k;
}
//3.插入左子树,右节点,失去平衡,先右旋再左旋
void left_right(Node** root) {
	right_rigth(&((*root)->left));
	left_left(&(*root));
}
//4.插入右子树左节点,失去平衡,先左旋再右旋
void rigth_left(Node** root) {
	left_left(&((*root)->right));
	right_rigth(&(*root));
}


//插入节点
void Insert_node(Datatype data, Node** root) {
	if (!(*root)) {
		(*root) = Create_node(data);
		return;
	}
	else {
		if (data < (*root)->data) {
			Insert_node(data, &((*root)->left));
			if (get_height((*root)->left) - get_height((*root)->right) > 1) {//如果出现失衡的情况
				if(data<(*root)->left->data)
					left_left(&(*root));
				else
					left_right(&(*root));
			}
		}
		else if (data > (*root)->data) {
			Insert_node(data, &((*root)->right));
			if (get_height((*root)->right) - get_height((*root)->left) > 1) {//如果出现失衡的情况
				if(data>(*root)->right->data)
					right_rigth(&(*root));
				else
					rigth_left(&(*root));
			}
		}
		else {
			printf("Do not insert numbers of the same size!\n");
			return;
		}
	}
	(*root)->heigh++;
}

//创建平衡二叉树
void Create_AVLtree(Node** T, Datatype* data,int n) {
	if (!data) {
		return;
	}
	for (int i = 0; i < n; i++) {
		Insert_node(data[i],T);
	}
}

 3.删除节点操作

在对平衡二叉树进行删除节点的操作时候,跟插入节点也是一样的,会出现失衡的情况,那这里就要通过旋转来去处理了,要进行那种旋转就要根据删除的节点属性去看,以下有4种情况:

  • 删除叶子结点
  • 删除结点只有左子树
  • 删除结点只有右子树
  • 删除结点有左、右子树

下面就一个一个来看,怎么去进行删除吧

3.1删除叶子节点

删除叶子节点后要看,平衡二叉树是否失衡,如果没有失衡就直接删除即可;如果出现了失衡的情况就要从根节点开始向上依次检索看从哪个位置开始失衡了,一经发现失衡就进行相对于的旋转处理,直到根结点为止。

平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

3.2删除只有一个左(右)子树的节点

这种情况就要用这个被删除节点的相邻节点来去顶替这个节点,然后整体进行相对于的旋转操作。如下图所示:

平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

3.3删除有左右子树的节点

 要删除的节点有左右子树的话,那么就找到左子树的最大节点或者找到右子树最小节点来替换掉这个节点,然后把这个节点的空间释放掉就行了。

平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树

3.4删除节点代码实现

//查找数据节点
Node* Search_node(Node *T,Datatype target) {
	if (!T) {
		return NULL;
	}
	if (target == T->data)
		return T;
	else if (target < T->data)
		Search_node(T->left, target);
	else
		Search_node(T->right, target);
}

//删除指定数据的节点
void Del_node(Node** T, Datatype target) {
	Node* dnode = Search_node(*T, target);
	if (!dnode){//如果查找不成功,就返回
		printf("bye~~~error\n");
		return;
	}
	if (target < (*T)->data) {
		Del_node(&(*T)->left, target);
		if (get_height((*T)->left) - get_height((*T)->right) > 1) {
			if (target < (*T)->left->data)
				left_left(&*T);
			else
				left_right(&*T);
		}
	}
	else if (target > (*T)->data) {
		Del_node(&(*T)->right, target);
		if (get_height((*T)->right) - get_height((*T)->left) > 1) {
			if (target < (*T)->right->data)
				rigth_left(&*T);
			else
				right_rigth(&*T);
		}
	}
	//此时(*T)就是要删除的节点
	//1.如果这个节点都有左右子树的话
	else if ((*T)->left && (*T)->right) {
		//找到右子树最左边的节点,也就是比这个要删除节点大一位的节点
		Node* min = (*T)->right;
		while (min->left)
			min = min->left;
		(*T)->data = min->data;
		Del_node(&(*T)->right, min->data);
	}
	//2.如果这个节点有一个左右子树或者没有子树的情况
	else {
		Node* dnode = (*T);
		(*T) = (*T)->left ? (*T)->left : (*T)->right;//把这个节点进行替换掉
		free(dnode);//释放空间,删除这个节点
	}
	//高度重新处理
	if((*T))
		(*T)->heigh=get_height((*T)->left)>get_height((*T)->right)? 
		get_height((*T)->left)+1: get_height((*T)->right)+1;
}

4.平衡二叉树相关操作

4.1查找数据

查找数据然后返回这个节点,我们直接通过二分查找就行了,代码如下:

//查找数据节点
Node* Search_node(Node *T,Datatype target) {
	if (!T) {
		return NULL;
	}
	if (target == T->data)
		return T;
	else if (target < T->data)
		Search_node(T->left, target);
	else
		Search_node(T->right, target);
}

4.2判断是否为平衡二叉树

根据平衡二叉树的特性,我们需要判断这个二叉树是否排序,是否满足左右子树高度差不大于1 ,这里就需要用到递归一层一层检索了,最后取和运算,代码如下:

//判断一个树是否为平衡二叉树
bool Judge(Node* T) {
	if (!T){
		printf("NULL\n");
		exit(0);
	}
	if(T->left->data>T->data||T->right->data<T->data)
		return false;
	if (abs(get_height(T->left) - get_height(T->right)) > 1)
		return false;
	else
		return true;
	return Judge(T->left)&&Judge(T->right);
}

4.3中序遍历输出

//中序遍历输出
void In_travel(Node* T) {
	if (!T)
		return;
	In_travel(T->left);
	printf("%d ", T->data);
	In_travel(T->right);
}

4.4销毁平衡二叉树

销毁平衡二叉树就要把每一个节点的空间释放掉,那就直接从下往上去释放空间,代码如下:

//销毁
void Destroy(Node** T) {
	if (!*T)
		return;
	Destroy(&(*T)->left);
	Destroy(&(*T)->right);
	free(*T);
}

以上就是本期的全部内容了,我们下一期再见!

分享一张壁纸: 平衡二叉树,数据结构与算法,数据结构,c语言,二叉树,递归,平衡二叉树文章来源地址https://www.toymoban.com/news/detail-850016.html

到了这里,关于数据结构-----平衡二叉树的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构之二叉树和平衡二叉树

    1、二叉树: 2、平衡二叉树:

    2024年04月17日
    浏览(44)
  • 数据结构之平衡二叉树的平衡调整

    1:LL型调整 2:RR型调整 3:LR型调整 4:RL型调整 5:总结 作者约定:将导致不平衡的结点称作 被破坏者 ,破坏了结点的平衡的结点成为 破坏者 ,经过调整可以让该树平衡的结点称为 调整结点 。 LL型不平衡调整方法:以调整结点为中心,进行右旋操作,就可以使树平衡。

    2024年02月09日
    浏览(47)
  • 数据结构之平衡二叉树详解

    平衡二叉树(balanced binary tree) 又称AVL树(Adelson-Velskii and Landis) 一棵平衡二叉树或者是空树,或者是具有下列性质的 二叉排序树 :         1,左子树与右子树的高度之差的绝对值小于等于1;         2,左子树和右子树也是平衡二叉排序树. 为了方便起见,给每

    2024年02月03日
    浏览(41)
  • 【数据结构】二叉排序树——平衡二叉树的调整

    参考视频: 懒猫老师-数据结构-(59)平衡二叉树【互动视频】 (1)什么是平衡二叉树 平衡二叉树(Balanced Binary Tree)是一种特殊的二叉查找树,它的目的是保持树的高度尽量平衡,以保证查找、插入、删除等操作的时间复杂度为 O(log n)。 常见的平衡二叉树算法包括 AVL 树、红

    2024年02月04日
    浏览(40)
  • 数据结构——常见二叉树的分类(完全二叉树、满二叉树、平衡二叉树、二叉搜索树、红黑树)

    专业术语 中文 描述 Root 根节点 一棵树的顶点 Child 孩子结点 一个结点含有的子树的根节点称为该结点的子节点 Leaf 叶子结点 没有孩子的节点 Degree 度 一个节点包含子树的数量 Edge 边 一个节点与另外一个节点的连接 Depth 深度 根节点到这个节点经过边的数量 Height 节点高度 从

    2024年02月03日
    浏览(44)
  • 数据结构-各种树(二叉树、二叉查找树、平衡二叉树、红黑树、B树、B+树)

    概念:二叉树(binary tree)是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树 特点:每个

    2024年02月09日
    浏览(48)
  • Java常见的数据结构:栈、队列、数组、链表、二叉树、二叉查找树、平衡二叉树、红黑树

    数据结构是计算机底层存储、组织数据的方式。是指数据相互之间是以什么方式排列在一起的。 通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率 栈 队列 数组 链表 二叉树 二叉查找树 平衡二叉树 红黑树... 后进先出,先进后出 数据进入栈模型的过程称为

    2024年02月07日
    浏览(46)
  • 【数据结构】二叉查找树和平衡二叉树,以及二者的区别

    目录 1、二叉查找树 1.1、定义  1.2、查找二叉树的优点  1.2、查找二叉树的弊端 2、平衡二叉树 2.1、定义 2.2、 实现树结构平衡的方法(旋转机制) 2.2.1、左旋 2.2.2、右旋 3、总结        二叉查找树又名二叉排序树,亦称二叉搜索树。是每个结点最多有两个子树的树结构

    2024年02月20日
    浏览(50)
  • 计算机基础--->数据结构(6)【AVL树(平衡二叉树)】

    平衡二叉树是一种特殊的二叉搜索树,他的左子树与右子树的高度差不超过1。并且左右两个子树都是一颗平衡二叉树。保持平衡的特性使得平衡二叉树的查询、插入和删除操作在平均和最坏情况下的时间复杂度都是 O(logn) ,其中n是树中节点的数量。 相比于普通的二叉搜索树

    2024年02月12日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包