数据结构之平衡二叉树C语言版

什么是平衡二叉树

平衡二叉树是具有平衡属性的有序二叉树所谓的平衡即当前树的左右子树高度差的绝对值不超过1。因为平衡二叉树是由苏联数学家Adelson-VelskiiLandis提出,所以又称为AVL树。

平衡二叉树的基本特点

  1. 是特殊的有序二叉树
  2. 左右子树高度差的绝对值不超过1
  3. 左右子树仍然是平衡二叉树

为什么会出现平衡二叉树

在学习平衡二叉树之前必定已经学过有序二叉树,有序二叉树的结构特点就是将数据有序的排好,查找起来快,但是有序二叉树有一个缺点,就是当节点呈现的状态是一边倒,那查找数据的时候就没有发挥出二叉树折半查找的优势了,这个时候是线性的查找(类似于链表的查找)。平衡二叉树就是解决有序二叉树一边倒的问题。如果有序二叉树是平衡的,那么查找数据就很快。时间复杂度为 O ( l o g n ) O(logn) O(logn)。这样就充分发挥了二叉树的优势。

二叉树四种不平衡的情况

当树的左右子树高度差的绝对值大于1的时候就需要进行旋转操作,将不平衡的树变成平衡的树。以下是会出现的四种不平衡的情况

  • 左左不平衡
  • 右右不平衡
  • 左右不平衡
  • 右左不平衡

左左不平衡旋转成平衡状态:

在这里插入图片描述

右右不平衡旋转成平衡状态:
在这里插入图片描述

左右不平衡旋转成平衡状态:

在这里插入图片描述

右左不平衡旋转成平衡状态:

在这里插入图片描述

上面是图解这四种不平衡状态旋转成平衡状态的情况。

C语言实现平衡二叉树

平衡二叉树的结构体描述:

#define Ty int  //以整型数据为例
typedef struct Node
{
   
	Ty data;             //数据
	int height;          //高度
	struct Node* LChild; //左子树
	struct Node* RChild; //右子树
}Node,AVLTree;

初始化函数:

AVLTree* creatAVLTree(Ty data)
{
   
    AVLTree* tree = (AVLTree*)malloc(sizeof(AVLTree));
    assert(tree);
    tree->data = data;
    tree->height = 0;
    tree->LChild = NULL;
    tree->RChild = NULL;
    return tree;
}

辅助宏函数:

//辅助函数
#define HEIGHT(x) ((x==NULL)?(-1):(x->height))
#define MAX(a,b)  ((a>b)?(a):(b))
//获取树的新高度
#define GET_NEW_HEIGHT(x) (MAX(HEIGHT(x->LChild),HEIGHT(x->RChild)) + 1)

使用宏函数的好处是运行过程中不需要进行函数压栈的操作,效率快一点。

前序遍历平衡二叉树:

//前序打印
void show_pre(AVLTree* root)
{
   
	if(root==NULL)
		return;
	printf("data:%d\theight:%d\n",root->data,root->height);
	show_pre(root->LChild);
	show_pre(root->RChild);
}

使用前序遍历能更好地看出节点的高度,更方便还原平衡二叉树。

四种不平衡状态旋转的算法实现:

算法核心思想:找到新根的位置,然后进行对应的调整,最后返回新根的地址,这样就实现了旋转的操作,因为旋转后节点的高度改变了,所以在返回之前先调整一下节点的高度。

例如:左左不平衡进行旋转操作

因为是左左不平衡,所以新根的位置是当前根的左子树,那就使用一个指针(newRoot)去接收当前根的左子树,然后使劲将当前根拉下来,让新根代替当前根的位置,那就必须将当前根的LChild指向newRoot的右子树(因为newRoot

  • 17
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
当然,下面是一个简单的平衡二叉树的C语言代码示例: ```c #include <stdio.h> #include <stdlib.h> // 定义二叉树节点结构 typedef struct Node { int data; // 节点值 struct Node* left; // 左子节点指针 struct Node* right; // 右子节点指针 int height; // 节点高度 } Node; // 计算节点的高度 int height(Node* node) { if (node == NULL) { return 0; } return node->height; } // 获取两个数中较大的值 int max(int a, int b) { return (a > b) ? a : b; } // 创建一个新节点 Node* createNode(int data) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->left = NULL; newNode->right = NULL; newNode->height = 1; return newNode; } // 执行右旋操作 Node* rightRotate(Node* y) { Node* x = y->left; Node* T2 = x->right; x->right = y; y->left = T2; y->height = max(height(y->left), height(y->right)) + 1; x->height = max(height(x->left), height(x->right)) + 1; return x; } // 执行左旋操作 Node* leftRotate(Node* x) { Node* y = x->right; Node* T2 = y->left; y->left = x; x->right = T2; x->height = max(height(x->left), height(x->right)) + 1; y->height = max(height(y->left), height(y->right)) + 1; return y; } // 获取节点的平衡因子 int getBalanceFactor(Node* node) { if (node == NULL) { return 0; } return height(node->left) - height(node->right); } // 插入节点 Node* insertNode(Node* node, int data) { if (node == NULL) { return createNode(data); } if (data < node->data) { node->left = insertNode(node->left, data); } else if (data > node->data) { node->right = insertNode(node->right, data); } else { // 忽略插入相同的节点 return node; } node->height = 1 + max(height(node->left), height(node->right)); int balanceFactor = getBalanceFactor(node); // 左-左情况,执行右旋操作 if (balanceFactor > 1 && data < node->left->data) { return rightRotate(node); } // 右-右情况,执行左旋操作 if (balanceFactor < -1 && data > node->right->data) { return leftRotate(node); } // 左-右情况,先对左子节点进行左旋,再对当前节点进行右旋 if (balanceFactor > 1 && data > node->left->data) { node->left = leftRotate(node->left); return rightRotate(node); } // 右-左情况,先对右子节点进行右旋,再对当前节点进行左旋 if (balanceFactor < -1 && data < node->right->data) { node->right = rightRotate(node->right); return leftRotate(node); } return node; } // 中序遍历二叉树 void inorderTraversal(Node* root) { if (root != NULL) { inorderTraversal(root->left); printf("%d ", root->data); inorderTraversal(root->right); } } int main() { Node* root = NULL; root = insertNode(root, 10); root = insertNode(root, 20); root = insertNode(root, 30); root = insertNode(root, 40); root = insertNode(root, 50); root = insertNode(root, 25); printf("中序遍历结果:"); inorderTraversal(root); return 0; } ``` 这段代码实现了一个平衡二叉树的插入和中序遍历操作。你可以根据需要自行修改和扩展。希望对你有所帮助!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值