AVL平衡树

AVL平衡树是一种二叉搜索树,且每个节点保持平衡。


节点平衡的标准是节点的左右子树高度的差属于[-1, 0, 1]之一


另外,树的高度等于从根结点到最深叶子节点的步数。特别地,root=NULL,高度=-1;叶子节点的高度等于0。


如果树种某节点不满足节点的平衡标准,那么需要对不满足标准的节点进行旋转。

总共分四类:left-left,left-right,right-right,right-left,如下图。具体的旋转方法也如下图所示。其中,ABCD可以为NULL,也可以不为NULL。在旋转中,需要对ABCD和345重新分配位置,且一个点都不能少。




注意,left-left与left-right的区别在root->left的平衡标准是否为-1,而right-right与right-left的区别在于root->right的平衡标准是否为1。


往AVL插入一个新值的过程:

1. 插入新值

2. 判断是否有节点失去平衡,如果是,修正该点平衡(如图1,搬动调整ABCD)

3.更新每个节点的高度,可以用来判断节点的平衡度。


下面是在Hackerrank上数据结构题目:向一棵AVL树插入新值,且所有点的值均不相同。

题目链接:https://www.hackerrank.com/challenges/self-balancing-tree(已通过)

<span style="font-size:14px;">/*
node 树的节点
ht   节点高度
val  节点值
left 左子树根
right右子树根
*/

/*
typedef struct node
{
    int val;
    struct node* left;
    struct node* right;
    int ht;             
} node;
*/

node * insert(node * root,int val)
{
	//1. 向以root为根的AVL插入val

   //新值一定插入为叶子节点
   if(root == NULL){
       node *p = new node;
       p->val = val;
       p->ht = 0;
       p->left = NULL;
       p->right = NULL;
       return p;
   }
   if(root->val > val){
       root->left = insert(root->left, val);
   }
   else if(root->val < val){
       root->right = insert(root->right, val);       
   }
   else{
       return root;
   }
   

   //2. 判断节点root是否平衡并进行旋转
   int lh(-1), rh(-1);
   if(root->left != NULL){
       lh = root->left->ht;
   }
   if(root->right != NULL){
       rh = root->right->ht;
   }
   
   node *rootL, *rootR, *tmp;
   if(lh - rh >= 2){                  //left                    
       int h1(-1), h2(-1);
       if(root->left->left != NULL)
           h1 = root->left->left->ht;
       if(root->left->right != NULL)
           h2 = root->left->right->ht;
       
       if(h1 - h2 == -1){            //left-right
           rootL = root->left;
           root->left = rootL->right;
           tmp = root->left->left;
           root->left->left = rootL;
           rootL->right = tmp;
       }
       rootL = root->left;          //left-left
       tmp = rootL->right;
       rootL->right = root;
       root->left = tmp;
       root = rootL;
   }
   else if(lh - rh <= -2){          //right
       int h1(-1), h2(-1);
       if(root->right->left != NULL)
           h1 = root->right->left->ht;
       if(root->right->right != NULL)
           h2 = root->right->right->ht;
       
       if(h1 - h2 == 1){           //right-left
           rootR = root->right;
           root->right = rootR->left;
           tmp = root->right->right;
           root->right->right = rootR;
           rootR->left = tmp;
       }
       rootR = root->right;        //right-right
       tmp = rootR->left;
       rootR->left = root;
       root->right = tmp;
       root = rootR; 
   }
   
   //3. 更新root和其左右子树的高度
   rootR = root->right;
   if(rootR != NULL)
		rootR->ht = 1 + max( (rootR->left == NULL? -1: rootR->left->ht), (rootR->right == NULL? -1: rootR->right->ht) );
   rootL = root->left;
   if(rootL != NULL)
		rootL->ht = 1 + max( (rootL->left == NULL? -1: rootL->left->ht), (rootL->right == NULL? -1: rootL->right->ht) );
   root->ht = 1 + max( (root->left == NULL? -1: root->left->ht), (root->right == NULL? -1: root->right->ht) );
    
   return root;
}</span>


AVL平衡树是一种自平衡二叉查找树,主要解决二叉查找树在插入和删除操作时可能会失去平衡的问题。在AVL平衡树中,每个节点都有一个平衡因子,即左子树的高度减去右子树的高度,平衡因子的值只能为-1、0、1三种。当插入或删除一个节点后,如果导致某个节点的平衡因子的绝对值大于1,就需要通过旋转操作来重新平衡这个节点及其子树。 下面是一个非指针实现的AVL平衡树的示例代码: ```c++ #include <iostream> using namespace std; const int MAXN = 100; class AVLTree { public: AVLTree() : size(0) {} bool insert(int val) { if (size == MAXN) return false; root = insert(root, val); size++; return true; } bool remove(int val) { if (size == 0) return false; root = remove(root, val); size--; return true; } void print() { inorder(root); } private: struct Node { int val, h; Node *l, *r; Node(int v, Node *L = NULL, Node *R = NULL) : val(v), h(0), l(L), r(R) {} int height() { return this ? h : -1; } int balance() { return r->height() - l->height(); } void update() { h = max(l->height(), r->height()) + 1; } Node *rotate_left() { Node *p = r; r = p->l; p->l = this; update(); p->update(); return p; } Node *rotate_right() { Node *p = l; l = p->r; p->r = this; update(); p->update(); return p; } Node *rotate_left_right() { r = r->rotate_right(); return rotate_left(); } Node *rotate_right_left() { l = l->rotate_left(); return rotate_right(); } }; Node *root; int size; Node *insert(Node *p, int val) { if (!p) return new Node(val); if (val < p->val) { p->l = insert(p->l, val); if (p->balance() == 2) { if (val < p->r->val) p = p->rotate_right_left(); else p = p->rotate_left(); } } else if (val > p->val) { p->r = insert(p->r, val); if (p->balance() == -2) { if (val > p->l->val) p = p->rotate_left_right(); else p = p->rotate_right(); } } p->update(); return p; } Node *remove(Node *p, int val) { if (!p) return NULL; if (val < p->val) { p->l = remove(p->l, val); if (p->balance() == -2) { if (p->l->balance() <= 0) p = p->rotate_right(); else p = p->rotate_left_right(); } } else if (val > p->val) { p->r = remove(p->r, val); if (p->balance() == 2) { if (p->r->balance() >= 0) p = p->rotate_left(); else p = p->rotate_right_left(); } } else { if (!p->l && !p->r) { delete p; return NULL; } else if (p->l) { Node *q = p->l; while (q->r) q = q->r; p->val = q->val; p->l = remove(p->l, q->val); if (p->balance() == -2) { if (p->l->balance() <= 0) p = p->rotate_right(); else p = p->rotate_left_right(); } } else { Node *q = p->r; while (q->l) q = q->l; p->val = q->val; p->r = remove(p->r, q->val); if (p->balance() == 2) { if (p->r->balance() >= 0) p = p->rotate_left(); else p = p->rotate_right_left(); } } } p->update(); return p; } void inorder(Node *p) { if (!p) return; inorder(p->l); cout << p->val << " "; inorder(p->r); } }; ``` 这里实现了AVL平衡树的插入、删除和中序遍历操作。其中,AVL平衡树的旋转操作被封装在了节点结构体中,包括左旋、右旋、左右旋和右左旋四种情况。具体实现时,需要注意节点的高度、平衡因子的计算和更新,以及对树的递归遍历等细节问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值