思想:
通过执行两次旋转操作,把节点从作为根的孙子节点之一的位置带到树的顶部。
首先,执行一次旋转,将该节点成为根的一个孩子节点。
接着,执行另一次旋转,使它成为根。
根据从根到插入节点的两个链接是否已相同方式定向,存在4种不同的情况:
左--左:从根处右旋转两次。
左--右:在左孩子进行左旋转,然后在根进行右旋转。
右--右:在根处左旋转两次。
右--左:在右孩子进行右旋转,然后在根进行左旋转。
程序:
void STinsert(Item item)
{
head = splay(head,item);
}
link splay(link h,Item item)
{
Key v = key(item);
if(h == z)
return NEW(item,z,z,l);
if(less(v,key(h->item)))//左
{
if(hl == z)
return NEW(item,z,h,h->N+1);
if(less(v,key(hl->item)))//左--左
{
hll = splay(hll,item);
h = rotR(h);
}
else //左--右
{
hlr = splay(hlr,item);
hl = rotL(hl);
}
return rotR(h);
}
else //右
{
if(hr ==z)
return NEW(item,h,z,h->N+1);
if(less(key(hr->item),v))//右--右
{
hrr = splay(hrr,item);
h = rotL(h);
}
else //右--左
{
hrl = splay(hrl,item);
hr = rotR(hr);
}
return rotL(h);
}
}
当我们使用伸展插入法向BST中插入一个节点时,我们不仅要把那个节点带到根处,而且要把我们在搜索路径上遇到的其他节点带到根附近。准确的说,我们所进行的旋转将从根到任何我们遇到的节点的距离降低了一半。