首页 > 其他分享 >【平衡二叉树】数据结构—平衡二叉树

【平衡二叉树】数据结构—平衡二叉树

时间:2024-08-06 23:25:07浏览次数:13  
标签:node Node right height 二叉树 key 平衡 数据结构 left

平衡二叉树(Balanced Binary Tree)是一种特殊的二叉树,它的左右子树的高度差不超过1,这样可以保证树的高度相对较低,从而使得查找、插入和删除操作的时间复杂度保持在 O\left ( \log n \right )

平衡二叉树的基本概念

1. 二叉树:每个节点最多有两个子节点,分别称为左子节点和右子节点。
2. 平衡条件:对于每个节点,左子树和右子树的高度差的绝对值不超过1。
3. 高度:树的高度是从根节点到最深叶子节点的最长路径上的边的数量。

 AVL树

AVL树是最早的自平衡二叉查找树,由G.M. Adelson-Velsky和E.M. Landis在1962年提出。AVL树通过在每个节点存储一个平衡因子(左子树高度减去右子树高度)来保持平衡。

AVL树的基本操作

1. 插入:插入新节点后,检查树的平衡情况,必要时进行旋转操作以保持平衡。
2. 删除:删除节点后,同样检查树的平衡情况,并进行旋转操作。
3. 旋转:包括左旋、右旋、左右旋和右左旋四种操作,用于调整树的结构。

AVL树的实现

下面是一个简单的AVL树实现,包括插入和旋转操作的示例代码:

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

// AVL树节点结构
typedef struct Node {
    int key;
    int height; // 节点的高度
    struct Node* left;
    struct Node* right;
} Node;

// 获取节点的高度
int height(Node* N) {
    if (N == NULL)
        return 0;
    return N->height;
}

// 获取平衡因子
int getBalance(Node* N) {
    if (N == NULL)
        return 0;
    return height(N->left) - height(N->right);
}

// 创建新节点
Node* newNode(int key) {
    Node* node = (Node*)malloc(sizeof(Node));
    node->key = key;
    node->left = NULL;
    node->right = NULL;
    node->height = 1; // 新节点的高度为1
    return node;
}

// 右旋转
Node* rightRotate(Node* y) {
    Node* x = y->left;
    Node* T2 = x->right;

    // 进行旋转
    x->right = y;
    y->left = T2;

    // 更新高度
    y->height = 1 + (height(y->left) > height(y->right) ? height(y->left) : height(y->right));
    x->height = 1 + (height(x->left) > height(x->right) ? height(x->left) : height(x->right));

    return x; // 返回新的根节点
}

// 左旋转
Node* leftRotate(Node* x) {
    Node* y = x->right;
    Node* T2 = y->left;

    // 进行旋转
    y->left = x;
    x->right = T2;

    // 更新高度
    x->height = 1 + (height(x->left) > height(x->right) ? height(x->left) : height(x->right));
    y->height = 1 + (height(y->left) > height(y->right) ? height(y->left) : height(y->right));

    return y; // 返回新的根节点
}

// 插入节点
Node* insert(Node* node, int key) {
    // 1. 执行常规的BST插入
    if (node == NULL)
        return newNode(key);

    if (key < node->key)
        node->left = insert(node->left, key);
    else if (key > node->key)
        node->right = insert(node->right, key);
    else // 不允许重复的键
        return node;

    // 2. 更新节点的高度
    node->height = 1 + (height(node->left) > height(node->right) ? height(node->left) : height(node->right));

    // 3. 检查平衡性
    int balance = getBalance(node);

    // 如果不平衡,有四种情况

    // 左左情况
    if (balance > 1 && key < node->left->key)
        return rightRotate(node);

    // 右右情况
    if (balance < -1 && key > node->right->key)
        return leftRotate(node);

    // 左右情况
    if (balance > 1 && key > node->left->key) {
        node->left = leftRotate(node->left);
        return rightRotate(node);
    }

    // 右左情况
    if (balance < -1 && key < node->right->key) {
        node->right = rightRotate(node->right);
        return leftRotate(node);
    }

    // 返回(未改变的)节点指针
    return node;
}

// 中序遍历
void inorder(Node* root) {
    if (root != NULL) {
        inorder(root->left);
        printf("%d ", root->key);
        inorder(root->right);
    }
}

int main() {
    Node* root = NULL;

    // 插入节点
    root = insert(root, 10);
    root = insert(root, 20);
    root = insert(root, 30);
    root = insert(root, 40);
    root = insert(root, 50);
    root = insert(root, 25);

    // 中序遍历
    printf("中序遍历AVL树:");
    inorder(root);
    printf("\n");

    return 0;
}

代码说明

1. 节点结构:`Node`结构体包含键值、节点高度和左右子节点的指针。
2. 高度和平衡因子的计算:`height`和`getBalance`函数用于计算节点的高度和获取平衡因子。
3. 旋转操作:`rightRotate`和`leftRotate`函数用于进行树的旋转,以保持平衡。
4. 插入操作:`insert`函数用于插入新节点并保持AVL树的平衡。
5. 中序遍历:`inorder`函数用于遍历树并输出节点的键值。

AVL树是一种自平衡的二叉查找树,能够在插入和删除操作后保持平衡,从而保证高效的查找性能。通过旋转操作,AVL树能够在动态数据集上保持良好的性能。以上代码展示了AVL树的基本实现,可以根据需要进行扩展和优化。

觉得有帮助的话点个赞吧!

标签:node,Node,right,height,二叉树,key,平衡,数据结构,left
From: https://blog.csdn.net/qq_64108165/article/details/140968428

相关文章

  • 二叉树刷题,bfs刷题
    有些题目,你按照拍脑袋的方式去做,可能发现需要在递归代码中调用其他递归函数计算字数的信息。一般来说,出现这种情况时你可以考虑用后序遍历的思维方式来优化算法,利用后序遍历传递子树的信息,避免过高的时间复杂度。遍历,对每一个结点进行操作,可以是找这个结点的旁边结点也可以......
  • 二叉树递归解决问题刷题 (一)
    遇到和深度相关的题目,可以用dfs递归遍历深度获取bfs结果来做513.找树左下角的值如何找二叉树最底层最左边节点的值呢,就是dfs遍历深度,来获取,最后一层的第一个元素就是。classSolution:def__init__(self):#记录二叉树的最大深度self.maxDepth=......
  • 数据结构学习之树结构
    前段时间刚好在学习机器学习中的决策树,想起多年前学习树这个数据结构的场景,刚好借此机会回归一下知识点。树是一种非常常见的数据结构,它由节点(Node)和边(Edge)构成。它有如下的一些特征:1.根结点(RootNode):树有且只有一个根结点,它是树的顶端结点。2. 结点(Node):每个结点包含一个值或......
  • NC 实现二叉树先序,中序和后序遍历
    系列文章目录文章目录系列文章目录前言前言前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。描述给定一棵二叉树,分别按照二叉树先序,中序和后序打印所有的节点。i......
  • 数据结构——链表
    数据结构——链表概念代码实现节点申请节点空间尾插头插尾删头删查找在指定位置之前插入数据在指定位置之后插入数据删除pos节点删除pos后一节点销毁链表概念链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的......
  • 数据结构----链表
        接下来我打算更新数据结构相关方面的知识,使用的语言是Java,但是其中的逻辑和思路并不影响。如果感兴趣可以关注合集。    希望大家看完之后可以自己去手敲实现一遍,同时在最后我也列出一些基本和经典的题目,可以尝试做一下。大家也可以自己去力扣或者洛谷牛客......
  • 「队列」实现FIFO队列(先进先出队列|queue)的功能 / 手撕数据结构(C++)
    概述队列,是一种基本的数据结构,也是一种数据适配器。它在底层上以链表方法实现。队列的显著特点是他的添加元素与删除元素操作:先加入的元素总是被先弹出。一个队列应该应该是这样的:--------------QUEUE-------------———————————......
  • Day21 二叉树Part8
    目录任务669.修剪二叉搜索树思路108.将有序数组转换为二叉搜索树思路538.把二叉搜索树转换为累加树思路心得体会任务669.修剪二叉搜索树给你二叉搜索树的根节点root,同时给定最小边界low和最大边界high。通过修剪二叉搜索树,使得所有节点的值在[low,high]中。修剪树不......
  • 从0开始的算法(数据结构和算法)基础(一)
        当我们学会算数开始,算法就无处不在,买菜的时候18元的菜,手上就20元和三张1块的,大多数的人都会全给然后找5块吧。它们是计算机科学的核心,在数字时代更是如此,是解决问题的关键,一个好的算法工程师,到哪去都是很吃香的,对于一个普通程序猿来说,能够掌握算法(不是知道,不会用),但算法......
  • 从0开始的算法(数据结构和算法)基础(二)
    算法效率的评估    评估算法效率的好坏主要涉及到算法的时间复杂度(TimeComplexity)、空间复杂度(SpaceComplexity)以及在实际应用中的运行性能。曾经调侃中文压缩包事件[1],白话、成语、文言文,大多数时候我们明意思白时间和知识量是递增的,时间增长和我们学习的文言文长短有......