一.AVL树的旋转
AVL树是平衡搜索二叉树的一种。
平衡因子:节点右树的高度减左树的高度,AVL树规定平衡因子的绝对值小于2。若不在这个范围内,说明该树不平衡。
AVL树节点:
struct AVLTreeNode
{AVLTreeNode(const T& data = T()): _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr), _data(data), _bf(0){}AVLTreeNode<T>* _pLeft;AVLTreeNode<T>* _pRight;AVLTreeNode<T>* _pParent;T _data;int _bf; // 节点的平衡因子
};
如果在一棵原本是平衡的AVL树中插入一个新节点,可能造成不平衡,此时必须调整树的结构, 使之平衡化。根据节点插入位置的不同,AVL树的旋转分为四种:
1. 新节点插入较高左子树的左侧---左左:右单旋
void RotateL(Node* pParent){Node* SubR = pParent->_pRight; Node* SubRL = SubR->_pLeft;pParent->_pRight = SubRL;if (SubRL)SubRL->_pParent = pParent;SubR->_pLeft = pParent;pParent->_pParent = SubR;if (pParent->_pParent == nullptr){_pRoot = SubR;SubR->_pParent = nullptr;}else{if (pParent->_pParent->_pLeft == pParent){pParent->_pParent->_pLeft = SubR;}else{pParent->_pParent->_pRight = SubR;}}SubR->_bf = SubRL->_bf = 0;}
2. 新节点插入较高右子树的右侧---右右:左单旋
void RotateR(Node* pParent){Node* SubL = pParent->_pLeft;Node* SubLR = SubL->_pRight;pParent->_pLeft = SubLR;if(SubLR)SubLR->_pParent = pParent;SubL->_pRight = pParent;pParent->_pParent = SubL;if (pParent->_pParent == nullptr){_pRoot = SubL;SubL->_pParent = nullptr;}else{if (pParent == pParent->_pParent->_pRight){pParent->_pParent->_pRight = SubL;}else{pParent->_pParent->_pLeft = SubL;}SubL->_pParent = pParent->_pParent;}SubL->_bf = SubLR->_bf = 0;}
3. 新节点插入较高左子树的右侧---左右:先左单旋再右单旋
void RotateLR(Node* pParent){Node* SubL = pParent->_pLeft;Node* SubLR = SubL->_pRight;RotateL(SubL);RotateR(pParent);if (SubLR->_bf == -1){SubL->_bf = 0;SubLR->_bf = 0;pParent->_bf = 1;}else if (SubLR->_bf == 1){SubL->_bf = -1;SubLR->_bf = 0;pParent->_bf = 0;}else{assert(false);}}
4. 新节点插入较高右子树的左侧---右左:先右单旋再左单旋
void RotateRL(Node* pParent){Node* SubR = pParent->_pRight;Node* SubRL = SubR->_pLeft;RotateR(SubR);RotateL(pParent);if (SubRL->_bf == 1){SubR->_bf = 0;pParent->_bf = -1;SubRL = 0;}else if(SubRL->_bf == 0){SubR->_bf = 0;pParent->_bf = 0;SubRL = 0;}else if (SubRL->_bf == -1){SubR->_bf = 1;pParent->_bf = 0;SubRL = 0;}else{assert(false);}}
二.AVL树的插入
插入一个节点后平衡因子可能会改变。所以不仅要改变指针方向,还要更新平衡因子的值。
bool Insert(const T& data){if (_pRoot == nullptr){_pRoot = new Node(data);return true;}Node* cur = _pRoot;Node* parent = _pRoot;while (cur){if (data < cur->_data){parent = cur;cur = cur->_pLeft;}else if (data < cur->_data){parent = cur;cur = cur->_pRight;}else{return false;}}cur = new Node(data);if (data < parent->_data){parent->_pLeft = cur;}else{parent->_pRight = cur;}//更新平衡因子while (parent){if (parent->_pLeft = cur){parent->_bf-- ;}else{parent->_bf++;}if (parent->_bf == 1 || parent->_bf == -1){cur = parent;parent = parent->_pParent;}else if (parent->_bf == 2 || parent->_bf == -2){if (parent->_bf == 2 && cur->_bf == 1){RotateR(parent);}else if (parent->_bf == -2 && cur->_bf == -1){RotateL(parent);}else if (parent->_bf == 2 && cur->_bf == -1){RotateRL(parent);}else{RotateLR(parent);}}else{assert(false);}}return true;}
三.AVL树的验证
1.求树的高度
size_t _Height(Node* pRoot){if (pRoot == nullptr){return 0;}int LestTreeHeight = _Height(pRoot->_pLeft);int RightTreeHeight = _Height(pRoot->_pRight);return LestTreeHeight > RightTreeHeight ? LestTreeHeight + 1 : RightTreeHeight + 1;}
2.验证是否为平衡二叉树
bool _IsAVLTree(Node* pRoot){if (pRoot == nullptr){return true;}int LestTreeHeight = _Height(pRoot->_pLeft);int RightTreeHeight = _Height(pRoot->_pRight);int diff = RightTreeHeight - LestTreeHeight;if (abs(diff) >= 2 || abs(diff) != pRoot->_bf){return false;}return _IsAVLTree(pRoot->_pLeft) && _IsAVLTree(pRoot->_pRight);}
3.测试用例验证
int main()
{int arr[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16,14 };AVLTree<int> a;for (int i = 0; i < sizeof(arr) / sizeof(arr[0]);i++){a.Insert(i);}cout << a.IsAVLTree() << endl;return 0;
}