自调整树

来源:互联网 发布:网络英雄洛克人第5部 编辑:程序博客网 时间:2024/05/29 15:39

自调整树

首先我们要明确的是二叉搜索树的作用是什么?

二叉搜索树,平衡树都是为了快速的查找,插入与删除,在这期间我们都可能要进行树的重新构建,这中极其的消耗空间与时间,或许我们还有其它的办法,是的,我们可以根据访问的概率来进行自调整树算法。

在自调整树中,有两种情况。

1)单一旋转,当访问孩子节点的时候,进行与父节点的旋转

2)重复进行孩子-父亲旋转,一直到被访问的元素位于根部。

现在针对移动到根部,进行修改的版本为“倾斜策略”,在之前的版本中是直接的从孩子节点向父节点进行不断的旋转,那么在新策略下面,我们同样的分3种情况来

我们用Q代表当前节点,P代表父亲节点,G代表祖父节点

1)若节点的父亲是根节点,那么直接的进行旋转OK

2)若是同构的情况:(1QP的左子树,PG的左子树

                   (2)或者另一种情况:QP的右子树,PG的右子树

那么这种情形下,假如(1),则先对P围绕着G进行右旋转,再对Q围绕P进行右旋转。(2)的情况正好相反

3)若是异构:QP的左子树,PG的右子树。那么先对Q围绕P进行右旋转,此时PQ的孩子节点。再对G进行一次左旋。另一种情况:QP的右子树,PG的左子树则正好相反。

倾斜策略是一种集中关注与元素而不是树的形状,但是如果靠近跟的元素访问的次数比较多,那么我们考虑的不是访问的概率,而是平衡。于是急需对平衡策略进行修改。

产生了半倾斜策略:

它对于同构倾斜只需要进行一次旋转,并将继续对被访问节点的父亲节点进行倾斜,而不是对节点自身进行倾斜。那么最后元素不一定位于根节点。

template<class T>//半倾斜策略,5种情形void  SplayTree::semisplay(SplayingNode<T>*p){ while(p!=root) {  if (p->parent->parent==0)//若找寻的节点的父节点为根节点  {   if (p->parent->left=p)//为左子树   {    rotateR(p);//右旋转   }   else    rotateL(p);//左旋转  }  else if (p->parent->left==p)//若父节点不是根节点,且为父节点的左节点  {   if (p->parent->parent->left==p->parent)//若父节点是祖父节点的左子树   {    rotateR(p->parent);//右旋转父节点,同构的情况    p=p->parent;
   }   else   {    rotateR(p);//当父节点为祖父节点的有节点时,即异构    rotateL(p);//左旋   }  }  else  {   if (p->parent->parent->right==p->parent)   {    rotateL(p->parent);//左旋父节点,只对父节点进行倾斜    p=p->parent;   }   else   {    rotateL(p);//若父节点不为根节点,且为父节点的右子树,且父节点为祖父节点的左子树    rotateR(p);//左旋再右旋   }   if (root==0)   {    root=p;   }  } }}


 

原创粉丝点击