zoukankan      html  css  js  c++  java
  • 【模板】左偏树

    一、左偏树的性质

    左偏树,又称可并堆,所以他有堆的性质。

    定义几个量:(val)表示该节点的值,(fa)表示该节点的父亲,(ch[2])表示该节点的两个儿子(因为他是二叉树),(dis)表示这个节点到离他最近的叶子节点的距离。

    性质一:该节点的val不大于该节点左右儿子的val

    证明:堆。

    性质二:该节点左儿子的dis不小于该节点右儿子的dis

    证明:左偏树的定义。为了更快的进行合并、查询、删除(快速提取最小值)。

    性质三:该节点的dis等于该节点右儿子的dis。

    证明:构造的。

    性质四:一棵n个节点的左偏树的节点的距离k最多为(log(n+1)-1)

    证明:因为左偏树是一棵二叉树,当他节点最少的时候他是一棵完全二叉树,所以(n>=2^(k+1)-1),那么(k<=log(n+1)-1)。(这个结论是用来证明左偏树的时间复杂度的)

    二、左偏树的主要操作

    左偏树的主要实现就是他的merge,我们删除,插入一个节点就是利用左偏树的merge函数进行操作的。

    merge函数的实现方法:

    首先,我们建出来的左偏树是一定要符合以上四个性质的,所以我们的merge就是为了在合并后,左偏树仍有这些性质。

    1.我们要保证性质一

    所以:

    if(val[x]>val[y]||(val[x]==val[y]&&x>y))//性质一
    {
    	swap(x,y);
    }
    

    2.我们要开始合并,我们将以节点y形成的左偏树和节点x的右子树合并,在让合并后所形成的的左偏树满足性质。

    ch[x][1]=merge(ch[x][1],y);//合并右子树和y
    

    3.合并后的左偏树要满足性质三

    dis[x]=dis[ch[x][1]]+1;//性质三
    

    4.我们要更新节点的fa

    fa[x]=fa[ch[x][0]]=fa[ch[x][1]]=x;//更新fa
    

    5.为了操作4,我们要return 根节点

    return x;
    

    综上,merge函数就是:

    int merge(int x,int y)
    {
    	if(!x||!y)
    	{
    		return x+y;
    	}
    	if(val[x]>val[y]||(val[x]==val[y]&&x>y))//性质一
    	{
    		swap(x,y);
    	}
    	ch[x][1]=merge(ch[x][1],y);//合并右子树和y
    	if(dis[ch[x][0]]<dis[ch[x][1]])//性质二
    	{
    		swap(ch[x][0],ch[x][1]);
    	}
    	fa[x]=fa[ch[x][0]]=fa[ch[x][1]]=x;//更新fa
    	dis[x]=dis[ch[x][1]]+1;//性质三
    	return x;
    }
    

    三、基于merge函数的操作

    删除某一节点(pop)

    我们只要合并这个节点的左右儿子即可。

    void pop(int x)
    {
    	val[x]=-1;
    	fa[ch[x][0]]=ch[x][0];
    	fa[ch[x][1]]=ch[x][1];
    	fa[x]=merge(ch[x][0],ch[x][1]);
    }
    

    求某一节点所在堆得最小值,并删除此节点

    xx=getfa(x);
    printf("%d
    ",val[xx]);
    pop(xx);
    

    另:

    有关getfa:

    一定要路径压缩,不然原来(O(logn))的查询,就会被一条链卡成(O(n))

    四、例题:

    1.罗马游戏
    2.Joint Stacks

  • 相关阅读:
    loadrunner-3-19LR常见函数
    loadrunner-3-18Service-Level Agreement(服务水平协议)
    loadrunner-3-15IP欺骗
    loadrunner-3-14集合点
    Python 静态类型检查 mypy 示例
    JavaScript 中 == 和 === 的区别
    Python 一键安装全部依赖包
    TypeError: 'NoneType' object is not subscriptable
    前端开发神器 VSCode 使用总结
    Next.js 配置接口跨域代理转发
  • 原文地址:https://www.cnblogs.com/2017gdgzoi44/p/11377317.html
Copyright © 2011-2022 走看看