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语言数据结构中定位函数Index的使用方法

    C语言的数据结构中,定位函数Index的使用方法主要涉及到数组和指针的相关操作。Index函数的作用是在数组中查找对应的元素,返回该元素的索引位置。以下是详细攻略: 一、Index函数的用法 Index函数的原型如下: void *index(const void *s, int c, size_t n); 其中,参数含义如下: s: 要查找的数组 c: 要…

    数据结构 2023年5月17日
    00
  • C语言实现带头结点的链表的创建、查找、插入、删除操作

    C语言实现带头结点的链表的创建、查找、插入、删除操作攻略 一、链表基本概念 链表是一种动态的数据结构,它可以在运行时动态地分配内存,支持数据的插入、删除等操作。链表(Linked List)由多个节点(Node)组成,每个节点包含两部分,一个是数据部分(Data),另一个是指向下一个节点的指针(Next)。 二、带头结点的链表 带头结点的链表是一种特殊的链表…

    数据结构 2023年5月17日
    00
  • Python数据结构之链表详解

    Python数据结构之链表详解 链表简介 链表是一种数据结构,其每个节点都包含一个指向下一个节点的指针。链表可以用来表示序列,集合或映射等数据结构。在Python中,链表通常由节点和链表类来实现。 单向链表 单向链表是一种链表,每个节点包含指向下一个节点的指针。在Python中,一个节点可以由一个简单的对象表示,而整个链表必须由相互链接的节点组成。 下面是一…

    数据结构 2023年5月17日
    00
  • 柏林噪声算法(Perlin Noise)

    概述 引述维基百科的介绍: Perlin噪声(Perlin noise,又称为柏林噪声)指由Ken Perlin发明的自然噪声生成算法,具有在函数上的连续性,并可在多次调用时给出一致的数值。 在电子游戏领域中可以透过使用Perlin噪声生成具连续性的地形;或是在艺术领域中使用Perlin噪声生成图样。 维基百科的介绍相当的官方,其实可以理解为一个随机函数,不…

    算法与数据结构 2023年4月17日
    00
  • Mysql Innodb存储引擎之索引与算法

    Mysql Innodb存储引擎之索引与算法 MySQL是一款非常受欢迎的关系型数据库,有许多的存储引擎可供选择,其中InnoDB是目前最受欢迎的存储引擎之一。索引是InnoDB存储引擎的一个重要特性,它可以大大提高数据库查询的效率。本文将详细讲解InnoDB存储引擎的索引与算法。 索引 索引是一种数据结构,它将表中的列与对应的行位置组成键值对,以便快速查找…

    数据结构 2023年5月17日
    00
  • C++线性表深度解析之动态数组与单链表和栈及队列的实现

    C++线性表深度解析之动态数组与单链表和栈及队列的实现 动态数组的实现 动态数组是一种可以动态扩展的数组结构,它的容量可以随着需要而动态增加。在C++中,使用vector类可以实现动态数组的功能。vector类相当于动态分配了一块内存空间,在使用时可以根据需要进行动态扩展。下面是一个示例代码: #include <vector> #include…

    数据结构 2023年5月17日
    00
  • Java中使用数组实现栈数据结构实例

    下面是Java中使用数组实现栈数据结构实例的完整攻略: 步骤一:定义栈类 我们可以通过定义一个名为 Stack 的类来创建栈类,其中包含以下属性: 一个整型的变量 top,用于存储当前栈顶的位置 一个整型的数组 items,用于存储栈中的元素 一个整型的变量 capacity,用于表示栈的容量 代码如下所示: public class Stack { pri…

    数据结构 2023年5月17日
    00
  • Lua教程(七):数据结构详解

    Lua教程(七):数据结构详解 Lua 中的数据结构广泛应用于各种计算机程序中。本文将详细介绍 Lua 中的数组、列表、栈、队列、集合和字典等数据结构的使用以及相关的函数。 数组 数组是存储在连续内存位置上的相同数据类型的元素集合。Lua 中的数组索引默认从 1 开始。下面是一些常用的 Lua 数组函数: table.concat(arr[, sep[, i…

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