Splay(伸展树)的基本操作(c++)

本文介绍了Splay树的基本概念和操作,包括左旋、右旋、伸展等,阐述了Splay树作为平衡树的特性,以及在二叉查找树中的应用。此外,还详细讲解了Splay树的前驱、后继、插入、删除、查找排名等基本操作的实现,并探讨了其时间复杂度。
摘要由CSDN通过智能技术生成
M y   f i r s t   b l o g \color{white}{\rm My\ first\ blog} My first blog
写 给 新 手 , 大 佬 勿 喷 {\rm 写给新手,大佬勿喷}

目录

  • 前置知识
  • Splay是什么
  • 支持的操作
    • 左旋
    • 右旋
    • 伸展
  • 基本操作
    • 前驱
    • 后继
    • 插入
    • 删除
    • 查某数排名
    • 查排名为x的数
  • 时间复杂度
  • 例题
  • 结语

前置知识

  • 平衡树
  • 二叉查找树
  • 树上操作
  • 指针
  • 函数运用
  • 基础数学知识

Splay是什么

Splay tree(伸展树)是一种 平衡树,由 Daniel SleatorRobert Endre Tarjan 在1985年发明,用于保证 二叉查找树尽量平衡1 ,同时维护二叉查找树的性质2,使得查找操作的时间复杂度变低3

Splay依赖于 伸展操作,而 伸展操作 依赖于 旋转4操作 。相对于其他平衡树,Splay代码较为简单,应用范围广,实用性较强,时间复杂度还行,不需要记录用于平衡树的冗余信息。

数据结构 Code

struct Node
{
   
	long long val,size,sum;//节点的值、以此节点为根的子树的大小、相同值的个数
	Node *lson,*rson,*fa;//其左儿子、右儿子、父亲的指针
}tree[1000000];

基本维护 Code

Node *None,*root;//备用空节点和根节点
int kl=2;//数组大小
void shaobing()
{
   
	Node *p=tree+1,*q=tree+2;
	p->val=100000000;
	q->val=-100000000;
	p->size=2;
	q->size=1;
	p->sum=q->sum=1;
	p->lson=q;
	q->fa=p;
	root=p;
}//新建两个哨兵,防止越界
void Update(Node *p)
{
   
	if(p==None) return;//空就不用理他
	p->size=p->sum;
	if(p->lson!=None) p->size+=p->lson->size;
	if(p->rson!=None) p->size+=p->rson->size;
}//更新操作,当一个节点的位置改变了或新插入了一个节点时,需要重新维护size和same

支持的操作

1.左旋

字面意思,就是将某个节点旋到它父亲节点的父亲节点位置,同时维护BST性质。

举个例子:
一棵树
然后我们需要将 4 号节点左旋,也就是将 4 号节点旋到 2 号节点的父亲位置。
第一步
4 号节点不可能有三个儿子,所以我们将把 2 号节点下移,同时将 2 号节点的左儿子连至 2 号节点的右儿子 7 号节点, 4 号节点的右儿子连至 2 号节点,这样子就能维护 BST 性质。
第二部
于是就变成了这样:
左旋变化
Code

void zig(Node *p)
{
   
	Node *Fa=p->fa;//指向它的父亲节点
	Fa->lson=p->rson;
	if(p->rson!=None) p->rson->fa=Fa;
	p->rson=Fa; 
	p->fa=Fa->fa;
	if(Fa->fa!=None) //需要特判,否则会出错
	{
   
		if(Fa->fa->lson==Fa)Fa->fa->lson=p;
		else Fa->fa->rson=p;
	}
	Fa->fa=p;
	Update(Fa);//先更新儿子节点,再更新父亲节点
	Update(p);
}

2.右旋

和左旋原理基本一样。上图(将 3 号节点旋至 5 号节点):
右旋变化
Code

void zag(Node *p)
{
   
	Node *Fa=p->fa;//指向它的父亲节点
	Fa->rson=p->lson;
	if(p->lson!=None) p->lson->fa=Fa;
	p->lson=Fa;
	p->fa=Fa->fa;
	if(Fa->fa!=None) //需要特判,否则会出错
	{
   
		if(Fa->fa->lson==Fa)Fa->fa->lson=p;
		else Fa->fa->rson=p;
	}
	Fa->fa=p;
	Update(Fa);//先更新儿子节点,再更新父亲节点
	Update(p);
}

3.伸展

伸展是Splay中最重要的操作,通俗的说, 它就是左旋和右旋外面套一层循环 ,通过指挥左旋和右旋来实现伸展,就好像人体通过扭动关节来伸懒腰。

伸展是将某一个节点通过旋转旋到另一个节点的儿子位置,如果是旋到根&#

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值