• AVL 平衡树


      AVL是一种平衡二叉树,它通过对二叉搜索树中的节点进行旋转使得二叉搜索树达到平衡。AVL在所有的平衡二叉搜索树中具有最高的平衡性。

    定义

        平衡二叉树或者为空树或者为满足如下性质的二叉搜索树:

    1. 左右子树的高度之差绝对值不超过1
    2. 左右子树仍然为平衡二叉树

        定义平衡因子 BF(x) = x的左子树高度 - x的右子树的高度。平衡二叉树的每个节点的平衡因子只能为-1, 0, 1.

    维持平衡思想

        若二叉树当前为平衡状态,此时插入/删除一个新的节点,此时有可能造成二叉树不满足平衡条件,此时需要通过对节点进行旋转来使得二叉树达到平衡状态。从被插入/删除的节点开始向上查找,找到第一个不满足 |BF| <= 1的祖先节点P,此时对P和P的子节点(或P的子节点的子节点)进行旋转(可能分为下面的四种情况)。

    旋转

        (1)LL型平衡旋转法 
        由于在A的左孩子B的左子树上插入结点F,使A的平衡因子由1增至2而失去平衡。故需进行一次顺时针旋转操作。 即将A的左孩子B向右上旋转代替A作为根结点,A向右下旋转成为B的右子树的根结点。而原来B的右子树则变成A的左子树。 
    LL旋转

        (2)RR型平衡旋转法 
        由于在A的右孩子C 的右子树上插入结点F,使A的平衡因子由-1减至-2而失去平衡。故需进行一次逆时针旋转操作。即将A的右孩子C向左上旋转代替A作为根结点,A向左下旋转成为C的左子树的根结点。而原来C的左子树则变成A的右子树。 
    RR旋转

        (3)LR型平衡旋转法 
        由于在A的左孩子B的右子数上插入结点F,使A的平衡因子由1增至2而失去平衡。故需进行两次旋转操作(先逆时针,后顺时针)。即先将A结点的左孩子B的右子树的根结点D向左上旋转提升到B结点的位置,然后再把该D结点向右上旋转提升到A结点的位置。即先使之成为LL型,再按LL型处理。 
    LR旋转 
        如图中所示,即先将圆圈部分先调整为平衡树,然后将其以根结点接到A的左子树上,此时成为LL型,再按LL型处理成平衡型。

        (4)RL型平衡旋转法 
        由于在A的右孩子C的左子树上插入结点F,使A的平衡因子由-1减至-2而失去平衡。故需进行两次旋转操作(先顺时针,后逆时针),即先将A结点的右孩子C的左子树的根结点D向右上旋转提升到C结点的位置,然后再把该D结点向左上旋转提升到A结点的位置。即先使之成为RR型,再按RR型处理。 
    RL旋转 
        如图中所示,即先将圆圈部分先调整为平衡树,然后将其以根结点接到A的左子树上,此时成为RR型,再按RR型处理成平衡型。

    实现(c++)

    #include<iostream>
    using namespace std;
    #define MAX(a, b) a > b? a:b
    struct TreeNode{
    	int data;
    	TreeNode* child[2];
    	int size;
    	int height;
    	int count;
    	TreeNode(int val){
    		data = val;
    		size = count = height = 1;
    		child[0] = child[1] = NULL;
    	}
    	void Update(){
    		size = count;
    		height = 1;
    		if (child[0]){
    			size += child[0]->size;
    			height = MAX(height, 1 + child[0]->height);
    		}
    		if (child[1]){
    			size += child[1]->size;
    			height = MAX(height, 1 + child[1]->height);
    		}
    	}
    };
    
    struct AVL{
    	TreeNode* root;
    	AVL() :root(NULL){};
    
    	int GetHeight(TreeNode* node){
    		if (!node)
    			return 0;
    		return node->height;
    	}
    	int GetSize(TreeNode* node){
    		if (!node)
    			return 0;
    		return node->size;
    	}
    
    	//注意这里使用指针的引用
    	void Rotate(TreeNode*& node, int dir){
    		TreeNode* ch = node->child[dir];
    		node->child[dir] = ch->child[!dir];
    		ch->child[!dir] = node;
    		node->Update();
    		node = ch;
    	}
    	void Maintain(TreeNode*& node){
    		if (!node){
    			return;
    		}
    		int bf = GetHeight(node->child[0]) - GetHeight(node->child[1]);
    		if (bf >= -1 && bf <= 1){
    			return;
    		}
    		if (bf == 2){
    			int bf2 = GetHeight(node->child[0]->child[0]) - GetHeight(node->child[0]->child[1]);
    			if (bf2 == 1){ //左左旋转
    				Rotate(node, 0);
    			}
    			else if (bf2 == -1){ //左右旋转
    				Rotate(node->child[0], 1);
    				Rotate(node, 0);
    			}
    		}
    		else if (bf == -2){
    			int bf2 = GetHeight(node->child[1]->child[0]) - GetHeight(node->child[1]->child[1]);
    			if (bf2 == 1){ //右左旋转
    				Rotate(node, 1);
    			}
    			else if (bf2 == -1){ //右右旋转
    				Rotate(node->child[1], 0);
    				Rotate(node, 1);
    			}
    		}
    
    	}
    	void Insert(TreeNode*& node, int val){
    		if (!node){
    			node = new TreeNode(val);
    		}
    		else if (node->data == val){
    			node->count++;
    		}
    		else{
    			int dir = node->data < val;
    			Insert(node->child[dir], val);
    		}
    		//维持树的平衡
    		Maintain(node);
    		//更新节点
    		node->Update();
    	}
    
    	//注意参数为指针的引用
    	void Delete(TreeNode*& node, int val){
    		if (!node){
    			return;
    		}else if (node->data == val){
    			if (node->child[0] && node->child[1]){
    				int dir = GetHeight(node->child[0]) < GetHeight(node->child[1]);
    				//将子树中较高的那棵,旋转
    				Rotate(node, dir);
    				//递归调用delete,直到叶子节点才进行真正的删除
    				Delete(node->child[! dir], val);
    			}
    			else{
    				TreeNode* tmp_node = NULL;
    				if (node->child[0]){
    					tmp_node = node->child[0];
    				}
    				else if (node->child[1]){
    					tmp_node = node->child[1];
    				}
    				delete node;
    				node = tmp_node; //使用引用
    			}
    		}
    		else{
    			int dir = node->data < val;
    			Delete(node->child[dir], val);
    		}
    		Maintain(node);	 //维持平衡
    		node->Update();	//更新节点
    	}
    	int GetKth(TreeNode* node, int k){
    		while (node){
    			if (! node->child[0]){
    				if (k <= node->count){
    					return node->data;
    				}
    				else{
    					k -= node->count;
    					node = node->child[1];
    				}
    			}
    			else{
    				if (node->child[0]->size < k && node->child[0]->size + node->count >= k){
    					return node->data;
    				}
    				else if (node->child[0]->size > k){
    					node = node->child[0];
    				}
    				else{
    					k -= (node->child[0]->size + node->count);
    					node = node->child[1];
    				}
    			}
    		}
    		return -1;
    	}
    };
    

     参考: 
    平衡树 balanced binary tree (AVL tree)   
    AVL树 模板

  • 相关阅读:
    667. Beautiful Arrangement II
    695. Max Area of Island
    485. Max Consecutive Ones
    coedforces #481Div(3)(ABCDEFG)
    躲藏
    车辆问题(贪心)
    最小化代价(优先队列)
    PUBG
    hdu 2647 Reward(拓扑排序+优先队列)
    HDU 3342 Legal or Not(判断环)
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4718491.html
Copyright © 2020-2023  润新知