• 文艺平衡树Splay


    Splay 是平衡树

    (Splay) 是平衡树的一种

    基本思想是, 对于查找频率较高的节点,使其处于离根节点相对较近的节点

    Spaly的基本操作有

    • rotate(旋转)
    • splay (伸展)
    • push_up
    • push_down
    struct Node {
    	int son[2], fa, val;
    	int size, flag;
    
    	void init(int _val, int _fa) {
    		val = _val; fa = _fa;
    		size = 1;
    	}
    }tr[N];
    

    rotate()

    这个旋转操作跟数据结构里学的平衡树旋转操作是一样的。

    如下图,画的是右旋 (x) 的操作,蓝色的边表示信息发生了改变

    image-20201110194445055

    void rotate(int x) {
    	int y = tr[x].fa, z = tr[y].fa;
    	int k = (tr[y].son[1] == x); // k = 0 表示 x 是 y 的左儿子
    	tr[z].son[tr[z].son[1] == y] = x, tr[x].fa = z;
    	tr[y].son[k] = tr[x].son[k ^ 1], tr[tr[x].son[k ^ 1]].fa = y;
    	tr[x].son[k ^ 1] = y, tr[y].fa = x;
    	push_up(y), push_up(x);
    }
    

    代码中修改信息的三行对应了三条蓝边,上图表示的情况是 (k=0)

    splay()

    接口 splay(int x,int k) 把节点 (u) 转到 (k) 下面,若 (k)(0) , 则转到根的位置

    void splay(int x, int k) {
    	while (tr[x].fa != k) {
    		int y = tr[x].fa, z = tr[y].fa;
    		if (z != k) {
    			if ((tr[y].son[1] == x) ^ (tr[z].son[1] == y))rotate(x);
    			else rotate(y); //转y才是log复杂度
    		}
    		rotate(x);
    	}
    	if (!k)root = x;
    }
    

    if ((tr[y].son[1] == x) ^ (tr[z].son[1] == y)) 表示的是不是链状,此时转两下 (x) ,若是链状,则需要先转一下 (y) 再转 (x) ,不能转两次 (x)

    push_up()

    类似线段树的 push_up() ,一般只需要维护 (size)

    void push_up(int u) {
    	tr[u].size = tr[tr[u].son[0]].size + tr[tr[u].son[1]].size + 1;
    }
    

    push_down()

    在需要 (lazytag) 时将标记下传

  • 相关阅读:
    【520】利用 TextBlob & Vader 进行情感分析
    【519】Visio 里面实现输入公式
    Xcode 复制多行/移动某行/删除多行 快捷键
    rosbag 时间和topic过滤
    卡方分布(Chi-squared)外点(outlier)剔除
    EVO使用方法详解
    CloudCompare分离点云地面点和非地面点
    slam方向期刊和会议汇总
    UrbanLoco数据集
    ElasticSearch学习笔记——ik分词添加词库
  • 原文地址:https://www.cnblogs.com/sduwh/p/13955695.html
Copyright © 2020-2023  润新知