AVLTree

左单旋:

思路:

1、创建节点subR和subRL
2、parent的右指向subRL
3、判断subRL是否存在
      若存在,subRL的父亲就是parent
      若不存在,也不影响
4、subR的左指向parent
      那么subR的父亲就是parent的父亲了
5、给parent的父亲创建一个节点ppNode
      parent的父亲也就是ppNode,也就是subR
6、如果ppNode是空的,那么subR就是根节点了,subR的父亲也就是为空
     如果ppNode不是空,且它的左孩子是parent,那么subR为ppNode的左孩子
     如果ppNode不是空,且它的右孩子是parent,那么subR为ppNode的右孩子
7、subR的父亲是ppNode
      parent的bf等于subR的bf等于0.
代码:
void RotateL(Node* parent)//左单旋
{
Node* subR = parent->_right;
Node* subRL = subR->_left;//先定义两节点
parent->_right = subRL;//parent的右指向subRL
if (subRL)//subRL可能不会存在,也可能存在
{
subRL->_parent = parent;
}
subR->_left = parent;//subR的左指向parent
subR->_parent = parent ->_parent;//subR的父亲就是parent的父亲了
Node* ppNode = parent->_parent;//定义ppNode节点为parent的父亲节点
parent->_parent = subR;//parent的父亲节点也就是subR
if (ppNode == NULL)//如果ppNode为空,
{
   _root = subR;
subR->_parent = NULL;
}
else if (ppNode->_left == parent)
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}
subR->_parent = ppNode;
parent->_bf = subR->_bf = 0;//更新平衡因子
}

----------------------------------------------------------------------------------------------------------------------------------

右单旋:

思路:

1、创建节点subL和subLR
2、parent的左指向subLR
3、判断subLR是否存在
      若存在,subLR的父亲就是parent
      若不存在,也不影响
4、subL的右指向parent
      那么subL的父亲就是parent的父亲了
5、给parent的父亲创建一个节点ppNode
      parent的父亲也就是ppNode,也就是subL
6、如果ppNode是空的,那么subL就是根节点了,subL的父亲也就是为空
     如果ppNode不是空,且它的左孩子是parent,那么subL为ppNode的左孩子
     如果ppNode不是空,且它的右孩子是parent,那么subL为ppNode的右孩子
7、subL的父亲是ppNode
      parent的bf等于subL的bf等于0.
代码:

void RotateR(Node* parent)//右单旋
{
Node* subL = parent->_left;//定义两个节点subL,subLR
Node* subLR = subL->_right;
parent->_left = subLR;//parent的左指向subLR
if (subLR)
{
subLR->_parent = parent;
}
subL->_right = parent;//subL的右指向parent
subL->_parent = parent->_parent;//subL的父亲就是parent的父亲
Node* ppNode = parent->_parent;//定义一个节点ppNode为parent的父亲节点
if (ppNode == NULL)
{
root = subL;
subL->_parent = NULL;
}
else if (ppNode->_left==parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
subL->_bf = parent->_bf = 0;

}

----------------------------------------------------------------------------------------------------------------------------------

左右双旋:

思路:

1、创建节点subL,subLR
     定义平衡因子bf=subLR->_bf
2、以parent->_left为轴左单旋
     再以parent为轴右单旋
3、若subLR的平衡因子为1,那么subL的平衡因子为-1,parent的平衡因子为0.
     若subLR的平衡因子为-1,那么subL的平衡因子为0,parent的平衡因子为1.
     若subLR的平衡因子为0,那么subL的平衡因子为0,parent的平衡因子为0.
4、将subLR的平衡因子置为0
代码:
void RotateLR(Node* parent)//左右双旋
{
Node* subL = parent->_left;//定义节点subL,subLR
Node* subLR = subL->_right;
int bf = subLR->_bf;//定义平衡因子,初始化为subLR的平衡因子
RotateL(parent->_left);//以parent的左为轴进行左单旋
RotateR(parent);//以parent为轴进行右单旋
//画完图一目了然
if (subLR->_bf == 1)//如果subLR的平衡因子为1,则subL和parent的平衡因子如下
{
subL->_bf = -1;
parent->_bf = 0;
}
else if (subLR->_bf == -1)//同上
{
subL->_bf = 0;
parent->_bf = 1;
}
else//subLR的平衡因子为0
{
subL->_bf = parent->_bf = 0;
}
subLR->_bf = 0;//最终将subLR的平衡因子置为0
}

----------------------------------------------------------------------------------------------------------------------------------

右左双旋:

思路:

1、创建节点subR,subRL
     定义平衡因子bf=subRL->_bf
2、以parent->_right为轴右单旋
     再以parent为轴左单旋
3、若subRL的平衡因子为1,那么subR的平衡因子为-1,parent的平衡因子为0.
     若subRL的平衡因子为-1,那么subR的平衡因子为0,parent的平衡因子为1.
     若subRL的平衡因子为0,那么subR的平衡因子为0,parent的平衡因子为0.
4、将subRL的平衡因子置为0
代码:
void RotateRL(Node* parent)//右左双旋
{
Node* subR = parnet->_right;
        Node* subRL = subR->_left;
int bf = subRL->_bf;
RotateR(parent->_right);
RotateL(parent);
if (subRL->_bf == 1)
{
subR->_bf = 0;
parent->_bf = -1;
}
else if (subRL->_bf == -1)
{
subR->_bf = 1;
parent->_bf = 0;
}
else
{
subR->_bf = parent->_bf = 0;
}
subRL->_bf = 0;

}

----------------------------------------------------------------------------------------------------------------------------------

Insert:

bool Insert(const K& key, const V& value)//插入
{
//1、AVL树位空树,直接插入为根节点
//2、插入值与根节点相同,返回false
//3、插入值小于根节点,递归到左子树,反之递归到右子树
if (_root == NULL)
{
_root = new Node(key, value);
return true;
}
Node* parent = NULL;
Node* cur = _root;//根节点给cur,根节点的父亲即为空
while (cur)//向下递归保证cur一直存在,直到cur为空说明已经递归到叶子节点了
{
if (cur->_key > key)//左递归
{
parent = cur;
cur = parent->_left;
}
else if (cur->_key < key)//右递归
{
parent = cur;
cur = parent->_right;
}
else//插入节点等于根节点
{
return false;
}
}
//到这里就找到key的父亲了,接下来判断key应该是其父亲的左孩子还是右孩子
cur = new Node(key, value);//
if (key > parent->_key)
{
parent->_right = cur;
cur->_parent = parent;
}
else if (key < parent->_key)
{
parent->_left = cur;
cur->_parent = parnet;
}
//到这里就找到key的插入点了,接下来判断平衡因子是否正确
//平衡因子有3种:0、正负1、正负2
//第一种情况:如果parent目前的_bf是0,说明之前parent的_bf是正负1,插入新节点后变为0了
//第二种情况:如果parent目前的_bf是正负1,说明之前parent的_bf是0,插入新节点后不仅会
//影响parent的_bf,而且会影响parent的parent的_bf,所以要向上回溯,直到所有的parent的_bf=0
//或者parent的_bf是正负2停止
//第三种情况:遇到parent的_bf是正负2,就需要旋转,旋转又分为左单旋、右单旋、左右双旋、右左双旋
while (parent)//这里找到了Parent,就以parent为条件
{
if (parent->_left = cur)//说明新插入节点插到了父亲的左孩子位置,那么父亲的
{                        //平衡因子需要减1
parent->_bf--;
}
else
{
parent->_bf++;//新插入节点插到了父亲的右孩子位置,父亲的bf要加1
}
if (parent->_bf == 0)//父亲的bf为0,不影响其他
{
break;
}
else if (parent->_bf == 1 || parent->_bf == -1)//回溯
{
cur = parent;
parent = cur->_parent;
}
else if (parent->_bf == 2 || parent->_bf == -2)//平衡因子大于绝对值1,需要旋转
//接下来判断是哪一种旋转
{


}
}
}

----------------------------------------------------------------------------------------------------------------------------------

InOrder中序遍历:
1、如果根为空,那么直接return 
2、如果根不为空,中序遍历根的左
     然后输出根
     然后再中序遍历根的右
3、如此形成一个递归,最终输出中序遍历结果
void InOrder()//中序、递归法
{
if (root == NULL)
return;
InOrder(root->_left);
cout << root->_key << " ";//该句必须放中间,保证“左根右”
InOrder(root->_right);
}
----------------------------------------------------------------------------------------------------------------------------------
IsBalence:
1、如果根为空,直接return true
2、如果根不为空,定义bf为根的右子树高度减去根的左子树高度
3、如果bf的绝对值大于1,或者bf不等于根的ebf,就输出false,并且输出平衡因子有问题的那个节点
4、如果bf正常,就递归根的左和根的右

bool IsBalance()//是否为平衡树
{
if (root == NULL)//如果根为空,该树满足是平衡树
return true;
int bf = Height(root->_right) - Height(root->_left);//定义bf为平衡因子,右子树高度减去左子树高度
if (abs(bf) > 1 || bf != root->_bf)//如果bf的绝对值大于1,或者bf不等于根节点的bf,那么就输出平衡因子有误的节点位置
{
cout << "平衡因子有误:" << root->_key << endl;
return false;
}
return IsBalance(root->_left) && IsBalance(root->_right);//根节点正常就继续向下递归
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值