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++ 数据结构:超详细讲解顺序表 什么是顺序表 顺序表是一种线性结构,它用一段地址连续的存储单元依次存储线性表中的各个元素。 顺序表的结构 顺序表由两部分组成,分别是元素存储区和表长度信息。元素存储区通常用数组实现,表长度信息记录表中元素的个数。 顺序表的操作 常见的顺序表操作包括: 初始化操作 插入操作 删除操作 查找操作 遍历操作 初始化顺序表 初始化…

    数据结构 2023年5月17日
    00
  • C语言 结构体数组详解及示例代码

    C语言 结构体数组详解及示例代码 结构体是C语言中最为基础的数据结构之一,它可以将多个数据类型组合成一个整体,方便地进行访问和管理。而结构体数组则是将多个相同结构体类型的变量按照一定规律排列在一起的一种数据结构。本文将详细讲解C语言中结构体数组的使用方法及示例代码。 定义结构体 首先,我们需要定义一个结构体类型。结构体类型需要指定名称、成员变量及其数据类型:…

    数据结构 2023年5月17日
    00
  • Java数据结构之KMP算法的实现

    Java数据结构之KMP算法的实现 1. KMP算法的概述 KMP算法的全称是Knuth-Morris-Pratt算法,是一种字符串匹配算法,用于在文本串S内查找一个模式串P的出现位置。它的特点是在P和S两个序列中,当匹配失败时,它会跳过P的部分已匹配的字符,利用这个信息来减少S和P之间的匹配次数,从而提高匹配效率。 2. KMP算法的实现 2.1 预处理失…

    数据结构 2023年5月17日
    00
  • Java 数据结构线性表之顺序存储详解原理

    Java 数据结构线性表之顺序存储详解原理 一、什么是线性表 线性表(Linear List)指的是同一类数据元素的集合,而且这些元素之间是有序的。线性表具有两个显著的特点:第一,有且仅有一个被称为“第一个”的数据元素;第二,有且仅有一个被称为“最后一个”的数据元素;此外,除第一个和最后一个数据元素外,其它数据元素均有且仅有一个直接前驱和一个直接后继。 二、…

    数据结构 2023年5月17日
    00
  • Java数据结构之线索化二叉树的实现

    Java数据结构之线索化二叉树的实现 线索化二叉树的概述 线索化二叉树(Threaded Binary Tree)是一种优化的二叉树结构。它的优点是可以在O(n)的时间复杂度内,进行中序遍历。而在普通二叉树中进行中序遍历需要的时间复杂度是O(nlogn)。线索化二叉树的原理是利用空闲的指针域,来记录中序遍历中前驱与后继结点的位置。线索化二叉树中会出现两种类型…

    数据结构 2023年5月17日
    00
  • C语言实现数据结构迷宫实验

    C语言实现数据结构迷宫实验攻略 简介 迷宫是计算机图形学中的一个经典问题,也是数据结构和算法中常见的题目。C语言是一种广泛使用的编程语言,具有充分的编程接口和功能,可以方便地实现迷宫算法和数据结构。 本文将详细讲解C语言实现数据结构迷宫实验的完整攻略,让读者能够更加深入地理解迷宫算法和数据结构的应用。 实现步骤 1. 创建迷宫结构体 首先需要创建一个迷宫结构…

    数据结构 2023年5月17日
    00
  • C语言数据结构旋转链表的实现

    C语言数据结构旋转链表的实现 1. 什么是旋转链表 旋转链表是一种特殊的链表,其特点是将链表的最后一个节点移动到最前面,形成一个环形链表的效果。比如下面这个链表: 1 -> 2 -> 3 -> 4 -> 5 经过一次旋转之后变成了: 5 -> 1 -> 2 -> 3 -> 4 2. 实现思路 旋转链表的实现思路…

    数据结构 2023年5月17日
    00
  • 一些常见的字符串匹配算法

    作者:京东零售 李文涛 一、简介 1.1 Background 字符串匹配在文本处理的广泛领域中是一个非常重要的主题。字符串匹配包括在文本中找到一个,或者更一般地说,所有字符串(通常来讲称其为模式)的出现。该模式表示为p=p[0..m-1];它的长度等于m。文本表示为t=t[0..n-1],它的长度等于n。两个字符串都建立在一个有限的字符集上。 一个比较常见…

    算法与数据结构 2023年4月25日
    00
合作推广
合作推广
分享本页
返回顶部