/*****/AVL树&红黑树

微笑     AVL树:

AVL树是高度平衡的二叉搜索树(优化了的搜索二叉树),它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度。

概念:
1、首先AVL树是一颗二叉搜索树。
2、其次它的左子树和右子树都是AVL树。
3、它的左子树和右子树的高度差不超过1。(通常情况下,为每个结点都加一个平衡因子(bf),这个平衡因子是右子树的高度减去左子树的高度)

微笑AVL树的性质:

1.左子树和右子树的高度之差的绝对值不超过1;

2.树中的每个左子树和右子树都是AVL树;

3.每个节点都有一个平衡因子,任一节点的平衡因子是1,0,-1;

 (平衡因子=右子树的高度-左子树的高度)

微笑平衡化旋转:

平衡化旋转
如果一棵树原来是平衡的二叉搜索树,现在向里面插入一个结点,造成了不平衡,这时候我们就要调整这棵树的结构,使之重新平衡。
首先关于平衡有以下几点需要强调一下:
1、如果插入一个结点,树的高度不变,则它就是平衡的。
2、旋转之后树的高度不变,这里的不变是指与插入之前的高度相同。
3、插入之后只会影响从插入点到根节点路径上的结点的平衡。
4、平衡因子的取值只可能是-2,-1,0,1,2,取-2或2时就出现不平衡了,这时就需要调整,调整之后树就平衡了。
5、注意,所有的插入都是建立在平衡二叉树的基础之上的。


1.左单旋:

void _RotateL(Node* parent)
{
	assert(parent);
	Node* subR = parent->_right;
	Node* subRL = subR->_left;
	parent->_right = subRL;
	if (subRL)
	{
		subRL->_parent = parent;
	}
	Node* ppNode = parent->_parent;
	subR->_left = parent;
	parent->_parent = subR;
	if (ppNode == NULL)
	{
		_root = subR;
		subR->_parent = NULL;
	}
	else
	{
		if (ppNode->_left == parent)
		{
			ppNode->_left = subR;
			subR->_parent = ppNode;
		}
		else
		{
			ppNode->_right = subR;
			subR->_parent = ppNode;
		}
	}
	parent->_bf = subR->_bf = 0;
}

2.右单旋:

void _RotateR(Node* parent)
{
	Node* subL = parent->_left;
	Node* subLR = subL->_right;
	parent->_left = subLR;
	if (subLR)
	{
		subLR->_parent = parent;
	}
	Node* ppNode = parent->_parent;
	subL->_right = parent;
	parent->_parent = subL;

	if (ppNode == NULL)
	{
		_root = subL;
		subL->_parent = NULL;
	}
	else
	{
		if (ppNode->_left == parent)
		{
			ppNode->_left = subL;
			subL->_parent = ppNode;
		}
		else
		{
			ppNode->_right = subL;
			subL->_parent = ppNode;
		}
	}
	parent->_bf = subL->_bf = 0;
}

3.左右双旋:(3种情况)

void _RotateLR(Node* parent)
{
	Node* subL = parent->_left;
	Node* subLR = subL->_right;
	int bf = subLR->_bf;
	_RotateL(subL);
	_RotateR(parent);

	if (bf == 0)
	{
		parent->_bf = subL->_bf = subLR->_bf = 0;
	}

	else if (bf == 1)
	{
		parent->_bf = 0;
		subL->_bf = -1;
		subLR->_bf = 0;
	}
	else  //bf == -1
	{
		parent->_bf = 1;
		subL->_bf = 0;
		subLR->_bf = 0;
	}
}
4.右左双旋
void _RotateRL(Node* parent)
    {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;
        int bf = subRL->_bf;

        _RotateR(parent->_right);
        _RotateL(parent);

        if (bf == 0)
        {
            parent->_bf = 0;
            subR->_bf = 0;
            subRL->_bf = 0;
        }
        else if (bf == 1)
        {
            parent->_bf = -1;
            subR->_bf = 0;
            subRL->_bf = 0;
        }
        else    //bf == -1
        {
            parent->_bf = 0;
            subR->_bf = 1;
            subRL->_bf = 0;
        }
    }

微笑AVL树的插入:

1.找到要插入的位置:

if (_root == NULL)
        {
            _root = new Node(key);
            return true;
        }
        Node* cur = _root;
        Node* parent = NULL;
        //找到要插入的节点的位置
        while (cur)
        {
            if (key > cur->_key)
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (key < cur->_key)
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                return false;   //表示已经存在,就不再插入了
            }
        }

2.插入节点:

 cur = new Node(key);
        if (key > parent->_key)
        {
            parent->_right = cur;
            cur->_parent = parent;
        }
        else
        {
            parent->_left = cur;
            cur->_parent = parent;
        }

3.更新平衡因子:

//更新平衡因子,分三种情况
        while (parent)
        {
            if (parent->_left == cur)
                parent->_bf--;
            else
                parent->_bf++;
            //1.
            if (parent->_bf == 0)
            {
                return true;
            }
            //2.
            else if (abs(parent->_bf) == 1)
            {
                cur = parent;
                parent = cur->_parent;
            }
            //3.
            else   //abs(parent->_bf) == 2
            {
                Node* subL = parent->_left;
                Node* subR = parent->_right;
                if (parent->_bf == -2 && subL->_bf == -1)
                {
                    _RotateR(parent);
                    return true;
                }
                else if (parent->_bf == 2 && subR->_bf == 1)
                {
                    _RotateL(parent);
                    return true;
                }
                else if (parent->_bf == -2 && subL->_bf == 1)
                {
                    _RotateLR(parent);
                    return true;
                }
                else // (parent->_bf == 2 && subR->_bf == -1)
                {
                    _RotateRL(parent);
                    return true;
                }
            }
        }

微笑 判断一个二叉树是否是AVL树?

一颗二叉树为AVL,得同时满足是搜索二叉树(节点左孩子的值小于节点的值,节点右孩子的值大于节点的值)及这棵树平衡(左右子树的高度差不超过1)。 

判断一颗搜索二叉树是不是AVL树,要求将时间优化到O(N).
思路:从根节点向上开始判断,并将高度传回上一层。
bool IsBlance()  
    {  
        bool flag = false;  
        _IsBlance(_root,flag);  
        return flag;  
    }  
  
    int _IsBlance(Node* root, bool &flag)  
    {  
        if (root == NULL)  
        {  
            flag = true;  
            return 0;  
        }  
  
        int L=_IsBlance(root->_left,flag);  
        if (flag == false)  
            return 0;  
  
        int R=_IsBlance(root->_right,flag);  
        if (flag == false)  
            return 0;  
  
        if (abs(R - L) < 2)      //满足平衡条件  
        {  
            return L>R ? L + 1 : R + 1;  //返回高的子树高度+1  
        }  
        else  
            flag = false;  
        return 0;  
    }  


微笑代码:

#pragma once


template<class K, class V>
struct AVLTreeNode
{
// 三叉链结构
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;


// K/V
K _key;
V _value;


// bf
int _bf;


AVLTreeNode(const K& key, const V& value)
:_left(NULL)
,_right(NULL)
,_parent(NULL)
,_key(key)
,_value(value)
,_bf(0)
{}
};


template<class K, class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
AVLTree()
:_root(NULL)
{}


~AVLTree()
{}


bool Insert(const K& key, const V& value)
{
if (_root == NULL)
{
_root = new Node(key, value);
return true;
}


Node* parent = NULL;
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}


cur = new Node(key, value);
if (parent->_key < key)
{
parent->_right =  cur;
cur->_parent = parent;
}
else
{
parent->_left = cur;
cur->_parent = parent;
}


// 更新平衡因子
while(parent)
{
if (cur == parent->_left)
parent->_bf--;
else
parent->_bf++;


if(parent->_bf == 0)
{
break;
}
else if (parent->_bf == 1 || parent->_bf == -1)
{
cur = parent;
parent = cur->_parent;
}
else // 2 -2
{
// 旋转
if(parent->_bf == 2)
{
Node* subR = parent->_right;
if (subR->_bf == 1)
{
RotateL(parent);
}
else // -1
{
RotateRL(parent);
}
}
else // -2
{
Node* subL = parent->_left;
if (subL->_bf == -1)
{
RotateR(parent);
}
else // 1
{
RotateLR(parent);
}
}


break;
}
}


return true;
}


void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;


parent->_right = subRL;
if(subRL)
subRL->_parent = parent;


subR->_left = parent;
Node* ppNode = parent->_parent;
parent->_parent = subR;


if (parent == _root)
{
_root = subR;
subR->_parent = NULL;
}
else
{
if (parent == ppNode->_left)
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}


subR->_parent = ppNode;
}


parent->_bf = subR->_bf = 0;
}


void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;


parent->_left = subLR;
if (subLR)
subLR->_parent = parent;


subL->_right = parent;


Node* ppNode = parent->_parent;
parent->_parent = subL;


if (ppNode == NULL)
{
_root = subL;
subL->_parent = NULL;
}
else
{
if (ppNode->_left == parent)
ppNode->_left = subL;
else
ppNode->_right = subL;


subL->_parent = ppNode;
}


parent->_bf = subL->_bf = 0;
}


void RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
int bf = subLR->_bf;


RotateL(parent->_left);
RotateR(parent);


if (bf == 0)
{
subLR->_bf = parent->_bf = subL->_bf = 0;
}
else if (bf == 1)
{
parent->_bf = 0;
subL->_bf = -1;
subLR->_bf = 0;
}
else//bf == -1
{
subL->_bf = 0;
subLR->_bf = 0;
parent->_bf = 1;
}
}


void RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;


RotateR(parent->_right);
RotateL(parent);


if (bf == 0)
{
parent->_bf = subRL->_bf = subR->_bf = 0;
}
else if (bf == 1)
{
subR->_bf = 0;
parent->_bf = -1;
subRL->_bf = 0;
}
else // bf == -1
{
parent->_bf = 0;
subR->_bf = 1;
subRL->_bf = 0;
}
}


void InOrder()
{
_InOrder(_root);
cout<<endl;
}


void _InOrder(Node* root)
{
if (root == NULL)
return;


_InOrder(root->_left);
cout<<root->_key<<" ";
_InOrder(root->_right);
}


// O(N*N) -> O(N)
bool IsBalance()
{
//return _IsBalance(_root);
int height = 0;
return _IsBalance(_root, height);
}


size_t _Height(Node* root)
{
if (root == NULL)
return 0;


int l = _Height(root->_left);
int r = _Height(root->_right);


return l > r ? l+1 : r+1;
}


// O(N*N)
//bool _IsBalance(Node* root)
//{
// if (root == NULL)
// return true;


// size_t l = _Height(root->_left);
// size_t r = _Height(root->_right);


// if (r-l != root->_bf)
// {
// cout<<"平衡因子异常?:"<<root->_key<<endl;
// return false;
// }


// return abs(r-l) < 2 &&
// _IsBalance(root->_left)&&
// _IsBalance(root->_right);
//}


bool _IsBalance(Node* root, int& height)
{
if (root == NULL)
{
height = 0;
return true;
}


int left, right;
if (_IsBalance(root->_left, left) && _IsBalance(root->_right, right)
&& abs(right-left) < 2)
{
height = left > right ? left+1 : right+1;


if (root->_bf != right - left)
{
cout<<"平衡因子异常:"<<root->_key<<endl;
return false;
}


return true;
}
else
{
return false;
}
}


protected:
Node* _root;
};


void TestAVLtree()
{
AVLTree<int, int> t1;
int a[] = {16, 3, 7, 11, 9, 26, 18, 14, 15};
for (size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i)
{
t1.Insert(a[i], i);
}


t1.InOrder();
cout<<"IsBalance?"<<t1.IsBalance()<<endl;


AVLTree<int, int> t2;
int a1[] = {4, 2, 6, 1, 3, 5, 15, 7, 16, 14};
for (size_t i = 0; i < sizeof(a1)/sizeof(a1[0]); ++i)
{
t2.Insert(a1[i], i);
//cout<<a1[i]<<"->IsBalance?"<<t2.IsBalance()<<endl;
}


t2.InOrder();
cout<<"IsBalance?"<<t2.IsBalance()<<endl;
}

微笑小记:

AVL树的效率
一棵AVL树有N个节点,其高度可以保持在log2N,插入/删除/查找的时间复杂度也是log2N。 (ps:log2N是表示log以2为底N的对数)


关于红黑树

红黑树首先是一棵搜索二叉树,树中的每一个结点的颜色不是黑色就是红色。它的特性如下:
  1、根节点是黑色
  2、每一个结点不是黑色就是红色
  3、不能有连续的两个红色结点
  4、从任意一个结点出发,到后代中空指针的路径上,均包含相同数量的黑色结点。


为什么要有红黑树???
  最开始我们学习了搜索二叉树,但是最后我们发现搜索二叉树有缺陷,之后我们又引入了AVL树。AVL树是一种高度平衡的二叉搜索树,能够满足增删查都是O(logN)的时间复杂度。既然AVL树已经满足了我们的期望,那么为什么还要引入红黑树呢?
  这是由于AVL树是高度平衡的二叉搜索树,维持一颗AVL树的代价相比于红黑树来说是非常大的,由于它的高度平衡,使得它几乎每次插入或者删除都需要调整树。而红黑树是一种近似平衡的二叉搜索树,它满足最长路径不超过最短路径的两倍,而且它易于维护,在插入的时候也不是每次都需要调整树。
  虽然红黑树整体性能上较AVL树能差一点,但是也不是差的太多,而且红黑树胜在易于维护,所以折中下来红黑树还是用的比较多的。

插入
 一般情况下,我么将要插入的结点都默认设置成红色的。
 1、如果插入的结点是根节点,则直接插入,并且将根节点染成黑色。
 2、如果要插入的位置的父亲是黑色的,那么直接插入。
 3、要插入的位置的父亲是红色的,这时再插入一个红色结点就会出现两个红色结点连续的情况,所以这时候我们就要调整树来重新恢复平衡。假设要插入的结点是cur,它的父亲是parent,它父亲的兄弟是uncle,它的祖父是grand。

删除
   红黑树的删除算法与二叉搜索树的删除算法类似,但是红黑树在删除之后还要再恢复树的平衡。首先我们要找到要删除的结点,如果要删除的结点有两个孩子,那么我们要在他的右子树寻找最左孩子,与他进行交换,然后将要删除的结点转换成这个最左结点。下面重点讲一下删除之后怎么恢复树的平衡,注意下面这些操作都是建立在要删除的结点的左孩子和右孩子至少有一个为空的情况下。

1、删除的结点是红色的,则直接删除,不会影响到树的平衡。
2、如果要删除的结点是黑色的,但是他的孩子是红色的,则直接删除这个结点,再把他的孩子变为黑色的。这样的话树的平衡也没有被改变。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值