前几天由于出行计划没有更博QwQ

(其实是因为调试死活调不出来了TAT我好菜啊)

伸展树英语:Splay Tree)是一种二叉查找树,它能在O(log n)内完成插入、查找和删除操作。它是由丹尼尔·斯立特Daniel Sleator)和罗伯特·塔扬在1985年发明的[1]

在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置。于是想到设计一个简单方法, 在每次查找之后对树进行调整,把被查找的条目搬移到离树根近一些的地方。伸展树应运而生。伸展树是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去。

它的优势在于不需要记录用于平衡树的冗余信息。


  • 可靠的性能——它的平均效率不输于其他平衡树[2]
  • 存储所需的内存少——伸展树无需记录额外的什么值来维护树的信息,相对于其他平衡树,内存占用要小。


伸展树最显著的缺点是它有可能会变成一条。这种情况可能发生在以非降顺序访问n个元素之后。然而均摊的最坏情况是对数级的——O(log n)

以上摘自中文Wikipedia

永远不要用单旋代替双旋...单旋那叫Spaly,Splay中的势能分析在单旋时会失效,复杂度不对的...(警告某整天单旋的ryf)

Rotate操作:

离散数学中,树旋转英语:Tree rotation)是在二叉树中的一种子树调整操作, 每一次旋转并不影响对该二叉树进行中序遍历的结果. 树旋转通常应用于需要调整树的局部平衡性的场合。

然后上几张图来作一下左旋/右旋的说明:

[学习笔记] Splay Tree 从入门到放弃

 

[学习笔记] Splay Tree 从入门到放弃

(第一张是动图不知道cnblogs能不能很好地滋磁GIF)

我们可以将左旋理解为将根旋转为右子节点的左子树,右旋为将根旋转为左子节点的右子树(往哪旋根就变成哪边的子树)

附C++袋马实现(左右合并,k=0为左旋,k=1为右旋)

#define lch chd[0]
#define rch chd[1]
#define kch chd[k]
#define xch chd[k^1]

void Rotate(Node* root,int k){
    Node* tmp=root->xch;
    if(root->prt==NULL)
        this->root=tmp;
    else if(root->prt->lch==root)
        root->prt->lch=tmp;
    else
        root->prt->rch=tmp;
    tmp->prt=root->prt;
    root->xch=tmp->kch;
    if(root->xch!=NULL)
        root->xch->prt=root;
    tmp->kch=root;
    root->prt=tmp;
}
Rotate

相关文章: