C++数据结构之AVL树的实现

C++数据结构之AVL树的实现

什么是AVL树

AVL树是一种自平衡二叉查找树,也就是说它通过旋转操作来保持树的平衡。

在AVL树中,任何节点的两个子树高度差不超过1。如果高度差大于1,则需要通过旋转操作来调整树的平衡。

AVL树提供了比红黑树更快的插入和删除操作,但是在读取数据时红黑树更快。

AVL树的实现

结构体定义

我们可以先定义一个结构体来表示AVL树中的节点:

struct Node  
{  
    int value;          // 当前节点的值  
    int height;         // 当前节点的高度  
    Node* left;         // 左子树指针  
    Node* right;        // 右子树指针  

    Node(int v)  
    {  
        value = v;  
        height = 1;  
        left = right = nullptr;  
    }  
};  

在这个结构体中,value表示节点存储的值,height表示当前节点的高度,left和right分别表示左右子树的指针。

插入操作

AVL树的插入操作比较复杂,需要分为以下几个步骤:

  • 向树中插入新节点
  • 更新节点的高度
  • 判断是否需要进行左旋或右旋或LR旋或RL旋操作

我们可以定义一个Insert函数来实现上述操作:

Node* Insert(Node* root, int value)  
{  
    // 向树中插入新节点  
    if (root == nullptr)  
        return new Node(value);  

    if (value < root->value)  
        root->left = Insert(root->left, value);  
    else  
        root->right = Insert(root->right, value);  

    // 更新节点的高度  
    root->height = max(GetHeight(root->left), GetHeight(root->right)) + 1;  

    // 判断是否需要进行左旋或右旋或LR旋或RL旋操作  
    int balance = GetBalance(root);  
    if (balance > 1 && value < root->left->value)  
        return RightRotate(root);  
    if (balance < -1 && value > root->right->value)  
        return LeftRotate(root);  
    if (balance > 1 && value > root->left->value)  
        return LeftRightRotate(root);  
    if (balance < -1 && value < root->right->value)  
        return RightLeftRotate(root);  

    return root;  
}

其中,GetHeight函数用于获取节点的高度,GetBalance函数用于获取节点的平衡因子(左子树高度减去右子树高度)。

LeftRotate、RightRotate、LeftRightRotate、RightLeftRotate分别表示左旋、右旋、LR旋、RL旋操作。

删除操作

AVL树的删除操作也比较复杂,需要分为以下几个步骤:

  • 找到待删除的节点
  • 删除节点
  • 更新祖先节点的高度
  • 判断是否需要进行左旋或右旋或LR旋或RL旋操作

我们可以定义一个Delete函数来实现上述操作:

Node* Delete(Node* root, int value)  
{  
    // 找到待删除的节点  
    if (root == nullptr)  
        return root;  

    if (value < root->value)  
        root->left = Delete(root->left, value);  
    else if (value > root->value)  
        root->right = Delete(root->right, value);  
    else  
    {  
        // 删除节点  
        if (root->left == nullptr || root->right == nullptr)  
            root = (root->left == nullptr ? root->right : root->left);  
        else  
        {  
            Node* cur = root->right;  
            while (cur->left != nullptr)  
                cur = cur->left;  
            root->value = cur->value;  
            root->right = Delete(root->right, cur->value);  
        }  
    }  

    if (root == nullptr)  
        return root;  

    // 更新祖先节点的高度  
    root->height = max(GetHeight(root->left), GetHeight(root->right)) + 1;  

    // 判断是否需要进行左旋或右旋或LR旋或RL旋操作  
    int balance = GetBalance(root);  
    if (balance > 1 && GetBalance(root->left) >= 0)  
        return RightRotate(root);  
    if (balance > 1 && GetBalance(root->left) < 0)  
        return LeftRightRotate(root);  
    if (balance < -1 && GetBalance(root->right) <= 0)  
        return LeftRotate(root);  
    if (balance < -1 && GetBalance(root->right) > 0)  
        return RightLeftRotate(root);  

    return root;  
}

其中,GetHeight函数与Insert函数中一样,GetBalance函数也与Insert函数中一样,LeftRotate、RightRotate、LeftRightRotate、RightLeftRotate也与Insert函数中一样。

示例

我们可以使用以下示例来测试我们实现的AVL树:

int main()  
{  
    Node* root = nullptr;  

    root = Insert(root, 10);  
    root = Insert(root, 20);  
    root = Insert(root, 30);  
    root = Insert(root, 40);  
    root = Insert(root, 50);  
    root = Insert(root, 25);  

    cout << "AVL Tree is:\n";  
    Print(root);  
    cout << endl;  

    root = Delete(root, 50);  

    cout << "AVL Tree after deletion is:\n";  
    Print(root);  
    cout << endl;  

    return 0;  
}  

其中,Print函数用于将AVL树的结构打印出来:

void Print(Node* root)  
{  
    if (root == nullptr)  
        return;  

    cout << root->value << " ";  
    Print(root->left);  
    Print(root->right);  
}  

执行以上程序会得到如下运行结果:

AVL Tree is:
30 20 10 25 40 50
AVL Tree after deletion is:
25 20 10 30 40

从结果可以看出,我们实现的AVL树能够正确地插入和删除节点,并且能够保持树的平衡。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++数据结构之AVL树的实现 - Python技术站

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

相关文章

  • C语言数据结构 链表与归并排序实例详解

    C语言数据结构 链表与归并排序实例详解 链表介绍 链表是一种数据结构,它对于存储数据是动态而灵活的。它可以根据我们的需要动态的分配内存空间。链表是由先后相连的数据单元(结点)组成,每个结点都包含了下一结点的地址信息,最后一个结点的地址信息为NULL。链表按照操作方式可以分为单向链表、双向链表与循环链表等几种类型。 归并排序原理 归并排序是一种分治思想的算法,…

    数据结构 2023年5月16日
    00
  • 中国剩余定理(CRT)学习笔记

    约定 \(A\perp B\) 表示 \(\gcd(A,B)=1\)。 \(A\mid B\) 表示 \(B\equiv 0\pmod{A}(A\neq0)\)。 引入 考虑以下这道题: 有物不知其數,三三數之剩二,五五數之剩三,七七數之剩二。 問物幾何?—— 《孫子算經》 也就是说,求出下列关于 \(x\) 方程组的最小整数解: \[\begin{case…

    算法与数据结构 2023年4月30日
    00
  • C语言数据结构之队列算法详解

    C语言数据结构之队列算法详解 什么是队列? 在计算机科学中,队列是一种抽象数据类型或线性数据结构。它具有先进先出(FIFO)的特性,即先进入队列的元素先被处理或先被移除。队列通常用于解决先到先服务的问题(如请求处理),但也常用于广泛的异步编程中。 队列的特点 队列通常具有以下特点: 队列可以为空; 队列从队首插入元素,从队尾移除元素; 队列只允许从队尾插入元…

    数据结构 2023年5月17日
    00
  • redis中的数据结构和编码详解

    Redis中的数据结构和编码详解 Redis中的数据结构 Redis支持以下五种数据结构: 字符串(string):最基本的数据类型,Redis中的字符串是二进制安全的,意味着您可以在字符串中存储任何数据。例如,您可以将图像文件或序列化对象存储为Redis字符串。字符串最大可以容纳512MB。 列表(list):Redis列表是字符串列表,其中的元素按照插入…

    数据结构 2023年5月17日
    00
  • C语言程序设计第五版谭浩强课后答案(第二章答案)

    首先,需要说明的是本题涉及到一个特定的知识领域,即C语言程序设计,以及该领域内某个具体教材的课后习题解答。因此,本攻略的重心将放在如何利用Markdown格式对该领域内的知识进行准确、清晰的表达和展示上。 下面是本攻略的目录: C语言程序设计第五版谭浩强课后答案(第二章答案)攻略 一、简介 二、题目列表 三、示例说明 示例一 示例二 四、总结 一、简介 本攻…

    数据结构 2023年5月17日
    00
  • 详解数据结构C语言实现之循环队列

    详解数据结构C语言实现之循环队列 什么是循环队列 循环队列是一种数据结构,它可以存储一组固定大小的元素,并且支持在队列尾部插入元素和在队列头部删除元素,当队列尾部没有空间时可以将队列头部空余的位置用来插入元素,实现循环的效果。循环队列的主要优点在于插入和删除元素的时间复杂度均为O(1),而不是O(n)。 如何实现循环队列 循环队列可以使用数组来实现,需要定义…

    数据结构 2023年5月17日
    00
  • Java数据结构之图的路径查找算法详解

    Java数据结构之图的路径查找算法详解 什么是图? 在计算机科学中,图是一种非常常见的数据结构,用于表示图形和网络等概念。图由节点和边组成,其中节点表示实体,边表示这些实体之间的关系。节点和边可以表示各种各样的实体和关系,因此图在计算机科学中具有广泛的应用。 图的路径查找算法 路径查找算法是一个用途广泛的算法,它用于查找从一个节点到另一个节点的路径。在图中,…

    数据结构 2023年5月17日
    00
  • C语言数据结构顺序表中的增删改(头插头删)教程示例详解

    C语言数据结构顺序表中的增删改(头插头删)教程示例详解 什么是顺序表? 顺序表是一种用数组实现的线性表,所有元素存储在一块连续的存储区中。顺序表的操作包括插入、删除、查找等。 常用的顺序表操作 增加元素 删除元素 修改元素 查找元素 以下以头插和头删为例,讲解如何在C语言数据结构顺序表中实现这些操作。 头插操作 头插的实现首先需要考虑插入位置的下标,由于是头…

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