为什么要引入旋转这一说法呢
?
因为在建立平衡二叉树,插入二叉树节点的时候,
如果发现平衡因子不是-1,0,1的时候就会进行调整,而平衡因子是判断一个二叉树的每层是否平衡的数据
在进程调制的时候就会有左单旋,右单旋,左右旋转,右左旋转,通过这四种旋转来使得不管插入多少数据都可以保持平衡二叉树的特点 对着四种旋转方式,我们以图的方式来进行理解:(图中的节点标记单词用于理解源代码)
源代码:
#include
<iostream>
using
namespace
std;
template
<
class
K
,
class
V
>
struct
AVLTreeNode
{
AVLTreeNode
<
K
,
V
>* _left;
AVLTreeNode
<
K
,
V
>* _right;
AVLTreeNode
<
K
,
V
>* _parent;
K
_key;
V
_value;
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
)
{ }
bool
Insert(
const
K
&
key
,
const
V
&
value
)
{
if
(_root ==
NULL
)
{
_root =
new
Node
(
key
,
value
);
return
true
;
}
//找新的节点要插入的位置
Node
* cur = _root;
Node
* parent =
NULL
;
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->_left = cur;
cur->_parent = parent;
}
else
{
parent->_right = cur;
cur->_parent = parent;
}
//更新平衡因子
//对于已经存在若干节点的二叉树,在插入一个新结点的时候,会影响其父节点到根节点这一路的节点的平衡因子
//需要自下而上的开始调整其平衡因子,如果当前父节点的bf=1或-1,则把当前节点的父亲给cur,把当前节点的父亲的父亲
//作为新的父亲节点,然后对新的父节点的bf做调整,调整过后如果bf=1或-1,依然继续向上调整,直到调整到根节点,因为
//父节点的父亲为NULL,无法进入循环。当在调整的过程中遇到父节点的bf=2或-2的时候,则需要通过旋转来调整二叉树
//右单旋:cur->bf=-1 parent->bf=-2
//左单旋:cur->bf=1 parent->bf=2
//右左单旋:cur->bf=-1 parent->bf=2
//左右单旋:cur->bf=1 parent->bf=-2
while
(parent)
{
//如果新的节点在父节点的左边,则平衡因子–
if
(parent->_left == cur)
{
parent->_bf–;
}
//如果新的节点在父节点的右边,则平衡因子++
else
{
parent->_bf++;
}
//平衡因子是0说明这个节点的高度是没有变化的,没有对父节点造成影响,所以不用再调整
if
(parent->_bf == 0)
{
break
;
}
//父节点平衡因子是1或-1说明该节点的平衡因子因为插入的节点而
//有了变化,而且会对父节点造成影响,所以继续向上调整
else
if
(parent->_bf == 1 || parent->_bf == -1)
{
cur = parent;
parent = parent->_parent;
}
else
//平衡因子为2或-2
{
if
(cur->_bf == 1)
{
//cur->bf=1,parent->bf=2 左单旋
if
(parent->_bf == 2)
{
RotateL(parent);
}
//cur->bf=1,parent->bf=-2 左右双旋
else
{
RotateLR(parent);
}
}
else
//cur->bf=-1
{
//cur->bf=-1,parent->bf=-2 右单旋
if
(parent->_bf == -2)
{
RotateR(parent);
}
//cur->bf=-1,parent->bf=2 右左单旋
else
{
RotateRL(parent);
}
}
break
;
}
}
return
true
;
}
void
InOrder()
{
_InOrder(_root);
cout << endl;
}
bool
IsBlance()
{
return
_IsBlance(_root);
}
protected
:
//左单旋
void
RotateL(
Node
*
parent
)
{
Node
* subR =
parent
->_right;
Node
* subRL = subR->_left;
parent
->_right = subRL;
if
(subRL)
subR->_parent =
parent
;
subR->_left =
parent
;
Node
* ppNode =
parent
->_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;
}
//右单旋
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;
subL->_parent = ppNode;
}
else
{
ppNode->_right = subL;
subL->_parent = ppNode;
}
}
parent
->_bf = subL->_bf = 0;
}
void
RotateLR(
Node
*
parent
)
{
RotateL(
parent
->_left);
RotateR(
parent
);
}
void
RotateRL(
Node
*
parent
)
{
RotateR(
parent
->_right);
RotateL(
parent
);
}
void
_InOrder(
Node
*
root
)
{
if
(
root
==
NULL
)
return
;
_InOrder(
root
->_left);
cout <<
root
->_key <<
” “
;
_InOrder(
root
->_right);
}
int
Hight(
Node
*
root
)
{
if
(
root
==
NULL
)
{
return
0;
}
int
left = Hight(
root
->_left);
int
right = Hight(
root
->_right);
return
left > right ? left+1 : right+1;
}
bool
_IsBlance(
Node
*
root
)
{
//二叉树为空认为是平衡二叉树
if
(
root
==
NULL
)
{
return
true
;
}
int
left_bf = Hight(
root
->_left);
int
right_bf = Hight(
root
->_right);
int
bf = right_bf – left_bf;
if
(bf !=
root
->_bf || df<-1 || df>1)
{
return
false
;
}
return
_IsBlance(
root
->_left) && _IsBlance(
root
->_right);
}
private
:
Node
* _root;
};
void
Test()
{
int
arr[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
//int arr[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
AVLTree
<
int
,
int
> t;
for
(
int
i = 0; i <
sizeof
(arr) /
sizeof
(arr[0]); i++)
{
t.Insert(arr[i], i);
}
t.InOrder();
cout <<
“是否是平衡二叉树:”
<< t.IsBlance() << endl;
}
int
main()
{
Test();
return
0;
}
结果:1 2 3 4 5 6 7 14 15 16
或:3 7 9 11 14 15 16 18 26
遇到的问题: