平衡搜索树的左单旋、右单旋、左右双旋、右左双旋

本文详细介绍了平衡搜索树中四种旋转操作:左单旋、右单旋、左右双旋及右左双旋的方法。通过这些操作可以保持树的平衡状态,确保高效的查找性能。文章还提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文要点:

平衡搜索树的左单旋、右单旋、左右双旋、右左双旋

 

在平衡搜索树中进行插入结点时,有可能会破坏整棵树的平衡。为了保证平衡不被破坏,就要对一些节点进行旋转,从而来降低树的高度,这样也能保证树的平衡。

一、左单旋:

\

(上图中的▲结点有可能是NULL,也有可能不为空。。。下同)

从图中可以看出,进行左单旋时,只是改变了parent的右指针以及subR的左指针指向。将subR的左子树(subRL)作为parent的右子树,并让parent作为subR的左子树。很明显,这样做就降低了这棵树的高度。

进行旋转时需要注意的两点:

1.改变subRL->_parent指向时,需要判断subRL是否为NULL,如果为空,就不能对其解引用。

2.parent是否为根节点?如果parent为根节点,那么旋转完成后只需将subR赋给根节点即可;但如果parent不为根节点,即parent是某一节点ppNode的子树,就要判断parent在ppNode的左还是右,这样才能确定subR的位置。

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void RotateLeft(Node* parent)   //左单旋
     {      
         Node* subR = parent->_right;
         Node* subRL = subR->_left;
 
         parent->_right = subRL;  //先改变parent的右指针
         if (subRL)  //subRL可能为NULL
         {
             subRL->_parent = parent;
         }
 
         Node* ppNode = parent->_parent;
         subR->_left = parent;
         parent->_parent = subR;
 
         if (ppNode == NULL)
         {
             _root = subR;
             subR->_parent = NULL;
         }
         else
         {
             //判断subR应链接在ppNode的左子树还是右子树
             if (ppNode->_left == parent)
                 ppNode->_left = subR;
             else
                 ppNode->_right = subR;
 
             subR->_parent = ppNode;
         }
     }

 

二、右单旋:

\

同左单旋一样,右单旋转是将subL的右子树结点赋给parent的左指针,并让parent自己作为subL的右子树。

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void RotateRight(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) //说明parent结点为根节点
     {
         _root = subL;
         subL->_parent = NULL;
     }
     else
     {
         //如果parent不为根节点,判断其在上一个结点的右还是左
         if (ppNode->_left == parent)
             ppNode->_left = subL;
         else
             ppNode->_right = subL;
 
         subL->_parent = ppNode;
     }
}

 

三、左右双旋:

了解了单旋之后,双旋就比较简单,只是进行了两步单旋而已

\

 

?
1
2
3
4
5
6
void RotateLR(Node* parent)     //左右双旋
     {
         RotateLeft(parent->_left);
         RotateRight(parent);
 
     }
四、右左双旋:

 

\

 

?
1
2
3
4
5
6
7
void RotateRL(Node* parent)     //右左双旋
{
     
     RotateRight(parent->_right);
     RotateLeft(parent);
 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值