平衡二叉树(AVL)

#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <stack>
#include <queue>
#include <Windows.h>
using namespace std;

typedef struct _Node
{
    int data;
    struct _Node *left;
    struct _Node *right;
    int bf;              //平衡因子
    _Node()
    {
        data = 0;
        left = NULL;
        right = NULL;
        bf = 0;
    }
}Node, *_PNode;

//******************************************AVL**********************************************begin

//参考 维基百科 AVL : http://zh.wikipedia.org/wiki/AVL%E6%A0%91
//                  http://www.cnblogs.com/abatei/archive/2008/11/17/1335031.html

//右旋
_PNode AVLLLTree(_PNode pNode)
{
    _PNode pNewNode = pNode->left;
    pNode->left = pNewNode->right;
    pNewNode->right = pNode;
    if (pNewNode->bf == 1)
    {
        pNode->bf = 0;
        pNewNode->bf = 0;
    }
    else
    {
        pNode->bf = 1;
        pNewNode->bf = -1;
    }
    return pNewNode;
}

//左旋
_PNode AVLRRTree(_PNode pNode)
{
    _PNode pNewNode = pNode->right;
    pNode->right = pNewNode->left;
    pNewNode->left = pNode;
    if (pNewNode->bf == -1)
    {
        pNode->bf = 0;
        pNewNode->bf = 0;
    }
    else
    {
        pNode->bf = -1;
        pNewNode->bf = 1;
    }
    return pNewNode;
}

//先右旋再左旋
_PNode AVLLRTree(_PNode pNode)
{
    _PNode pLeft = pNode->left;
    _PNode pNewNode = pLeft->right;
    pLeft->right = pNewNode->left;
    pNode->left = pNewNode->right;
    pNewNode->left = pLeft;
    pNewNode->right = pNode;
    switch (pNewNode->bf )
    {
    case 1:
        pLeft->bf = 0;
        pNode->bf = -1;
        break;
    case -1:
        pLeft->bf = 1;
        pNode->bf = 0;
        break;
    }
    pNewNode->bf = 0;
    return pNewNode;
}

//先左旋再右旋
_PNode AVLRLTree(_PNode pNode)
{
    _PNode pRight = pNode->right;
    _PNode pNewNode = pRight->left;
    pRight->left = pNewNode->right;
    pNode->right = pNewNode->left;
    pNewNode->left = pNode;
    pNewNode->right = pRight;
    switch (pNewNode->bf)
    {
    case 1:
        pNode->bf = 0;
        pRight->bf = -1;
        break;
    case -1:
        pNode->bf = 1;
        pRight->bf = 0;
        break;
    }
    pNewNode->bf = 0;
    return pNewNode;
}
_PNode pAvlRoot
= NULL; //AVL的根节点 stack<_PNode> sAvl; //保存从根节点到插入点的路径节点 bool AVLRotateTree(_PNode pNode, int bf) { bool bTallChange = true; _PNode pChild; _PNode pNewNode; if (2 == bf) { pChild = pNode->left; if (1 == pChild->bf) { pNewNode = AVLLLTree(pNode); } else if (-1 == pChild->bf) { pNewNode = AVLLRTree(pNode); } else { pNewNode = AVLLLTree(pNode); bTallChange = false; } } else if (-2 == bf) { pChild = pNode->right; if (1 == pChild->bf) { pNewNode = AVLRLTree(pNode); } else if (-1 == pChild->bf) { pNewNode = AVLRRTree(pNode); } else { pNewNode = AVLRRTree(pNode); bTallChange = false; } } if (!sAvl.empty()) { _PNode pParent = sAvl.top(); if (pParent->data > pNewNode->data) { pParent->left = pNewNode; } else if (pParent->data < pNewNode->data) { pParent->right = pNewNode; } } else { pAvlRoot = pNewNode; } return bTallChange; } //插入节点 void AVLInsertNode(int key) { if (BSTSearch(pAvlRoot, key)) //找到,不能插入直接返回 { return; } _PNode pNode = new Node; pNode->data = key; if (NULL == pAvlRoot) { pAvlRoot = pNode; return; } while (!sAvl.empty()) //清空栈 { sAvl.pop(); } _PNode p = pAvlRoot; while (NULL != p) { sAvl.push(p); if (key < p->data) { p = p->left; } else if (key > p->data) { p = p->right; } } _PNode pre = sAvl.top(); if (key < pre->data) { pre->left = pNode; } else if (key > pre->data) { pre->right = pNode; } int bf; while (!sAvl.empty()) { pre = sAvl.top(); sAvl.pop(); bf = (pre->data > key) ? 1 : -1; pre->bf += bf; bf = pre->bf; if (bf == 0) { break; } else if (2 == bf || -2 == bf) { AVLRotateTree(pre, bf); break; } } } //删除节点 void AVLRemoveNode(int key) { _PNode pNode = pAvlRoot; while (!sAvl.empty()) { sAvl.pop(); } while (NULL != pNode) { if (key < pNode->data) { sAvl.push(pNode); pNode = pNode->left; } else if (key > pNode->data) { sAvl.push(pNode); pNode = pNode->right; } else { _PNode pPreNode = sAvl.top(); if (NULL == pNode->left || NULL == pNode->right) //3、该节点只有一条子树 { if (NULL != pNode->left) { if (pNode == pAvlRoot) { pAvlRoot = pNode->left; } else if (pPreNode->left == pNode) { pPreNode->left = pNode->left; } else { pPreNode->right = pNode->left; } } else { if (pNode == pAvlRoot) { pAvlRoot = pNode->right; } else if (pPreNode->left == pNode) { pPreNode->left = pNode->right; } else { pPreNode->right = pNode->right; } } } else //4、该节点有左右子树 { _PNode pPre = pNode; sAvl.push(pNode); _PNode pSearch = pNode->right; while (NULL != pSearch->left) //5、找该节点右子树的最小值,即真正删除的点 { sAvl.push(pSearch); pPre = pSearch; pSearch = pSearch->left; } sAvl.pop(); //删除的点没用,将删除的点弹栈 pNode->data = pSearch->data; if (pPre->left == pSearch) { pPre->left = pSearch->right; } else { pPre->right = pSearch->right; } } int bf; while (!sAvl.empty()) { pPreNode = sAvl.top(); sAvl.pop(); bf = (pPreNode->data > key) ? -1 : 1; pPreNode->bf += bf; bf = pPreNode->bf; if (0 != bf) { if (1 == bf || -1 == bf || !AVLRotateTree(pPreNode, bf)) { break; } } } break; } } } //******************************************AVL***********************************************end

转载于:https://www.cnblogs.com/venow/archive/2012/08/09/2629094.html

### AVL树的定义 AVL树是一种自平衡二叉搜索树,以其发明者G.M.Adelson-Velsky和E.M.Landis的名字命名[^3]。它通过维护树的高度平衡来确保操作的时间复杂度保持在O(log n)级别。具体来说,在AVL树中,任意节点的两个子树的高度差(称为平衡因子)最多为1。 #### 平衡条件 - 对于任何一个节点,其左子树和右子树都必须是AVL树。 - 节点的平衡因子范围限定为{-1, 0, 1}。 --- ### AVL树的实现 以下是基于C++语言的一个典型AVL树实现框架: #### 结构体定义 ```cpp struct AVLNode { int key; int height; AVLNode* left; AVLNode* right; AVLNode(int k) : key(k), height(1), left(nullptr), right(nullptr) {} }; ``` #### 获取高度函数 用于计算某个节点的高度。 ```cpp int getHeight(AVLNode* node) { if (node == nullptr) return 0; return node->height; } ``` #### 更新高度函数 每次修改树结构后都需要更新节点的高度。 ```cpp void updateHeight(AVLNode* node) { if (node != nullptr) { node->height = std::max(getHeight(node->left), getHeight(node->right)) + 1; } } ``` #### 左旋操作 当右子树过重时执行左旋。 ```cpp AVLNode* rotateLeft(AVLNode* y) { AVLNode* x = y->right; AVLNode* T2 = x->left; // 执行旋转 x->left = y; y->right = T2; // 更新高度 updateHeight(y); updateHeight(x); return x; // 新的根节点 } ``` #### 右旋操作 当左子树过重时执行右旋。 ```cpp AVLNode* rotateRight(AVLNode* x) { AVLNode* y = x->left; AVLNode* T2 = y->right; // 执行旋转 y->right = x; x->left = T2; // 更新高度 updateHeight(x); updateHeight(y); return y; // 新的根节点 } ``` #### 插入操作 插入过程中可能会破坏平衡,因此需要进行相应的旋转调整。 ```cpp AVLNode* insert(AVLNode* root, int key) { if (root == nullptr) { return new AVLNode(key); } if (key < root->key) { root->left = insert(root->left, key); } else if (key > root->key) { root->right = insert(root->right, key); } else { return root; // 不允许重复键值 } // 更新当前节点的高度 updateHeight(root); // 计算平衡因子并判断是否失衡 int balanceFactor = getHeight(root->left) - getHeight(root->right); // 进行必要的旋转调整 if (balanceFactor > 1 && key < root->left->key) { return rotateRight(root); // 单右旋 } if (balanceFactor < -1 && key > root->right->key) { return rotateLeft(root); // 单左旋 } if (balanceFactor > 1 && key > root->left->key) { root->left = rotateLeft(root->left); // 先左旋再右旋 return rotateRight(root); } if (balanceFactor < -1 && key < root->right->key) { root->right = rotateRight(root->right); // 先右旋再左旋 return rotateLeft(root); } return root; } ``` --- ### 应用场景 AVL树适用于那些频繁查询而较少插入或删除的应用场合。由于其严格的平衡约束,使得查找效率非常高,但在大量动态数据集中的表现可能不如红黑树灵活。常见的应用领域包括但不限于: - 数据库索引设计:快速定位记录的位置。 - 编译器优化:存储符号表以便高效访问变量信息。 - 文件系统的元数据管理:加速文件检索速度。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值