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

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

介绍

AVL树是一种自平衡二叉搜索树,它保证了所有节点的左右子树高度差不超过1,从而提高了查找、插入和删除操作的效率。本篇文章将介绍如何使用C语言实现AVL树,并提供两个例子以说明实现方法。

实现方法

结构体定义

首先,定义AVL树节点的结构体,包括该节点存储的值、该节点的高度、该节点的左右子树指针。

typedef struct AVLNode {
    int value;
    int height;
    struct AVLNode* left;
    struct AVLNode* right;
} AVLNode;

AVL树的基本操作函数

1. 计算节点高度

计算节点高度的函数可以递归实现,即左右子树高度的最大值加一。如果节点为NULL,其高度为0。

int height(AVLNode* node) {
    if (node == NULL) {
        return 0;
    }
    return 1 + max(height(node -> left), height(node -> right));
}

2. 计算平衡因子

平衡因子是指左子树高度减去右子树高度的差。如果平衡因子的绝对值大于1,则需要进行旋转以保持树的平衡。

int balance_factor(AVLNode* node) {
    if (node == NULL) {
        return 0;
    }
    return height(node -> left) - height(node -> right);
}

3. 左旋转操作

左旋转是指将某个节点的右子树旋转到它的左子树位置,使得该节点成为其右子树的左子树。左旋转需要保持树的平衡性。

AVLNode* left_rotate(AVLNode* node) {
    AVLNode* right_child = node -> right;
    AVLNode* left_subtree = right_child -> left;
    right_child -> left = node;
    node -> right = left_subtree;
    node -> height = max(height(node -> left), height(node -> right)) + 1;
    right_child -> height = max(height(right_child -> left), height(right_child -> right)) + 1;
    return right_child;
}

4. 右旋转操作

右旋转是指将某个节点的左子树旋转到它的右子树位置,使得该节点成为其左子树的右子树。右旋转需要保持树的平衡性。

AVLNode* right_rotate(AVLNode* node) {
    AVLNode* left_child = node -> left;
    AVLNode* right_subtree = left_child -> right;
    left_child -> right = node;
    node -> left = right_subtree;
    node -> height = max(height(node -> left), height(node -> right)) + 1;
    left_child -> height = max(height(left_child -> left), height(left_child -> right)) + 1;
    return left_child;
}

5. 插入操作

插入操作需要找到对应的插入位置,并在插入后保持树的平衡性。首先插入节点,并递归调整其祖先节点的平衡因子,如果平衡因子的绝对值超过1,则进行相应的旋转操作使得树重新平衡。

AVLNode* insert(AVLNode* root, int value) {
    if (root == NULL) {
        AVLNode* new_node = (AVLNode*)malloc(sizeof(AVLNode));
        new_node -> value = value;
        new_node -> height = 1;
        new_node -> left = NULL;
        new_node -> right = NULL;
        return new_node;
    }
    if (value < root -> value) {
        root -> left = insert(root -> left, value);
    } else {
        root -> right = insert(root -> right, value);
    }
    root -> height = max(height(root -> left), height(root -> right)) + 1;
    int bf = balance_factor(root);
    if (bf > 1 && value < root -> left -> value) {
        return right_rotate(root);
    }
    if (bf > 1 && value > root -> left -> value) {
        root -> left = left_rotate(root -> left);
        return right_rotate(root);
    }
    if (bf < -1 && value < root -> right -> value) {
        root -> right = right_rotate(root -> right);
        return left_rotate(root);
    }
    if (bf < -1 && value > root -> right -> value) {
        return left_rotate(root);
    }
    return root; 
}

例子1:插入数字

以下示例代码演示了如何使用上述AVL树的基本操作实现对数字的插入。

AVLNode* 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);

例子2:查找最小节点

除了插入操作外,还可以实现其他操作,例如查找AVL树中的最小节点。以下示例代码演示了如何使用递归实现查找AVL树中的最小节点。

AVLNode* min_node(AVLNode* root) {
    if (root == NULL || root -> left == NULL) {
        return root;
    }
    return min_node(root -> left);
}

总结

本文详细介绍了如何使用C语言实现AVL树的基本操作,包括计算节点高度、计算平衡因子、左旋转、右旋转及插入操作。并通过两个示例演示了如何插入数字及查找AVL树中的最小节点。使用AVL树可以提高二叉搜索树操作的效率,对于需要频繁进行插入、删除操作的数据结构场景来说,尤其有用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言数据结构之平衡二叉树(AVL树)实现方法示例 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • MySQL索引底层数据结构详情

    MySQL索引底层数据结构详情 MySQL是一种关系型数据库,在设计和使用表时,常常需要使用索引来提高数据库的查询效率。那么,这些索引究竟是如何工作的呢?本文将介绍MySQL索引的底层数据结构,并提供两个示例以帮助读者更好地理解。 索引是什么? 索引是数据库中一种特殊的数据结构,用于加速查询操作。在MySQL中,通常使用B+Tree作为索引的底层数据结构。 …

    数据结构 2023年5月17日
    00
  • 深入浅析C语言中堆栈和队列

    深入浅析C语言中堆栈和队列 堆栈(Stack) 堆栈是一种先进后出(Last In First Out,LIFO)的线性数据结构,只允许在一端进行插入和删除操作。堆栈在C语言中常用于函数调用时的参数传递、表达式求值和程序中断处理等场景。 实现堆栈的基本操作 下面是堆栈的基本操作,可以用数组来实现: 初始化 #define MAX_SIZE 100 // 假设…

    数据结构 2023年5月17日
    00
  • 详解C语言内核中的链表与结构体

    详解C语言内核中的链表与结构体 1. 链表的概念 链表是一种线性数据结构,由多个节点组成,每个节点包含了两部分内容:数据和指针。 链表有多种类型,但其中最常见的是单向链表和双向链表。在单向链表中,每个节点只包含一个指针,它指向下一个节点;在双向链表中,每个节点包含两个指针,一个指向上一个节点,一个指向下一个节点。 链表的特点是可以动态地添加或删除节点,是一种…

    数据结构 2023年5月17日
    00
  • Python数据结构与算法之链表定义与用法实例详解【单链表、循环链表】

    Python数据结构与算法之链表定义与用法实例详解 什么是链表? 链表是一种常见的数据结构,它由一个个的节点组成,每个节点包含两部分,一部分存储数据,一部分存储下一个节点在哪里的指针。通过节点之间的指针,就可以将节点串起来,形成一个链表。 链表和数组是两种截然不同的数据结构,数组的元素在内存中是连续存储的,而链表的节点却可以分散在内存的不同位置,这也是链表灵…

    数据结构 2023年5月17日
    00
  • C数据结构之双链表详细示例分析

    作为本网站的作者,我很高兴为你讲解C数据结构之双链表详细示例分析的完整攻略。 双链表简介与定义 双链表是链表的一种,在链表中每一个节点都有一个指针域,指向下一个节点,这个指针域称为next指针;而在双链表中每一个节点也有两个指针域,一个指向前驱节点,另一个指向后继节点,即prev指针与next指针。由于双链表存在两个指针域,因此它支持双向遍历,无论是正向还是…

    数据结构 2023年5月17日
    00
  • C语言 数据结构之链表实现代码

    下面就是关于C语言数据结构之链表实现代码的完整攻略。 什么是链表 链表是一种基础的数据结构,它是由一系列的节点所组成,每个节点会包含自己的数据和指向下一个节点的指针。 链表分为单向链表、双向链表和循环链表等多种类型,常见的是单向链表和双向链表。 链表的优点 相对于数组,链表具有下述优点: 链表的长度可以无限增长,不存在数组固定长度的问题; 插入和删除元素时,…

    数据结构 2023年5月17日
    00
  • Java数据结构之线段树的原理与实现

    Java数据结构之线段树的原理与实现 什么是线段树 线段树是一种基于分治思想的数据结构,它可以用来解决各种区间查询问题,例如区间求和、最大值、最小值等等。在算法竞赛和数据结构课程中,线段树被广泛应用,是一种非常实用的数据结构。 线段树的基本原理 线段树是一种二叉树,它的每个节点包含一个区间,叶子节点表示区间中的单个元素,非叶子节点表示区间的合并。 线段树的建…

    数据结构 2023年5月17日
    00
  • java编程队列数据结构代码示例

    下面是“Java编程队列数据结构代码示例”的完整攻略。 什么是队列 队列是一种有序的数据结构,特点是先进先出(FIFO)。队列中不管是插入操作还是删除操作,都是在队列的两端进行的,插入操作在队列的尾部进行,删除操作在队列的头部进行。队列的一个重要用途是在计算机的操作系统中,实现进程和所有需要等待资源的实体之间的交互。 队列的实现 队列数据结构可以采用数组或链…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部