Treap总结(未完工)

\(Treap = Tree + Heap\)

树堆(Treap),在数据结构中也称Treap,是指有一个随机附加域满足堆的性质的二叉搜索树,其结构相当于以随机数据插入的二叉搜索树。其基本操作的期望时间复杂度为O(logn)。相对于其他的平衡二叉搜索树,Treap的特点是实现简单,且能基本实现随机平衡的结构。
                                                                                        ----百度百科

要了解Treap,就先要看看什么是二叉搜索树

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

Treap既有BST的性质,也有堆的性质,Treap的每个结点额外附加一个随机值(优先级),让他们按照关键码构成BST的同时也满足堆的性质(父节点优先级高于或低于子节点优先级),因为优先级是随机的,这样在绝大多数情况下我们得到的树都是平衡的,不容易被卡成链, 单次操作期望时间复杂度为O(logn)。

操作:

1.定义

struct Treap {
    int dat, val;
    int cnt, size, l, r;
} e[N];

dat 随机优先级; val BST关键码; cnt 当前结点数量; size 子树结点数量; l,r 左右儿子。
2.更新

void update(int p) {
    e[p].size = e[e[p].l].size + e[e[p].r].size + e[p].cnt;
}

更新结点size值。
3.新建结点

int newpoint(int val) {
    e[++tot].val = val;
    e[tot].dat = rand();
    e[tot].cnt = e[tot].size = 1;
    return tot;
}

4.建树

void build() {
    newpoint(-inf); newpoint(inf);
    root = 1; e[root].r = 2; update(root);
}

初始化两个结点,设置为无限大和无限小。
5.左右旋转
左右旋转是在保证BST性质前提下(中序遍历不变)将一个结点向上或者向下转,实质上是父节点变成了子节点,子节点变成了父节点。
左旋和右旋分别对应着将左儿子翻上来和将右儿子翻上来。

具体操作

void zig(int &p) {//左旋
    int q = e[p].l;
    e[p].l = e[q].r; e[q].r = p; p = q;
    update(e[p].r); update(p);
}
void zag(int &p) {//右旋
    int q = e[p].r;
    e[p].r = e[q].l; e[q].l = p; p = q;
    update(e[p].l); update(p);
}
//p引用的是旋转前的根结点

6.插入
插入一个值为val的结点,若存在关键码为val的结点,将此结点数量 + 1,若不存在,根据val大小和当前结点val大小向左右两边找,最后新建结点,返回时要维护堆性质。

void insert(int &p, int val) {
    if(p == 0) {
        p = newpoint(val); return ;
    }
    if(e[p].val == val) {
        e[p].cnt++; update(p);
        return ;
    }
    if(val < e[p].val) {
        insert(e[p].l, val);
        if(e[p].dat < e[e[p].l].dat) zig(p);
    } else {
        insert(e[p].r, val);
        if(e[p].dat < e[e[p].r].dat) zag(p);
    }
    update(p);
}

7.删除结点
删除一个值为法val的结点,先在树中查找值为val的结点:
1.若结点cnt(数量) 大于1,则可以直接减1,返回;
2.若结点数量为1,将其向下旋转,转到叶结点时直接删除;
注意:在向下旋转时应维护堆的性质,若是大根队,选取子节点中dat大的结点与其交换。

void delet(int &p, int val) {
    if(p == 0) return ;
    if(val == e[p].val) {
        if(e[p].cnt > 1) {
            e[p].cnt--; update(p); return ;
        } else {
            if(e[p].l || e[p].r) {//不为叶结点
                if(e[e[p].l].dat > e[e[p].r].dat || !e[p].r)
                    zig(p), delet(e[p].r, val);
                else
                    zag(p), delet(e[p].l, val);
                update(p);
            } else p = 0;
        }//else
        return ;
    }
    if(val < e[p].val) delet(e[p].l, val);
    else delet(e[p].r, val);
    update(p);
}

原文地址:https://www.cnblogs.com/mcggvc/p/12275388.html

时间: 2024-08-30 09:50:37

Treap总结(未完工)的相关文章

可持久化Treap(fhq Treap,非旋转式Treap)学习(未完待续)

简介: Treap,一种表现优异的BST 优势: 其较于AVL.红黑树实现简单,浅显易懂 较于Splay常数小,通常用于树套BST表现远远优于Splay 或许有人想说SBT,SBT我没有实现过,据说比较快 但是SBT.Splay以及旋转版Treap等BST都不可以比较方便地实现‘可持久化操作 Treap=Tree+Heap Treap是一颗同时拥有二叉搜索树和堆性质的一颗二叉树 Treap有两个关键字,在这里定义为: 1.key,满足二叉搜索树性质,即中序遍历按照key值有序 2.fix,满足堆

本周小结(未完工)

上周总结 学习的知识 FHQ非旋treap (万能头文件竟然不能用merge) CDQ分治 (两三个函数长一个样) 负载平衡问题 (才学会,还是太菜了) 线段树(启发式)合并 (不太会用.jpg) 复习的知识 各种数论知识 线性Dp和树形Dp 基本数据的结构 做题情况 AC 55道,AC率约为 40% 还行吧QAQ 新发现 万物皆可二分(QAQ) 写错变量名调一年 取模分清 \(1e9+7\) 和\(1e9+9\) DFS套DP套数据结构优化 毒瘤 .io真是个好东西 发现弱势 各种计数类题目

关于企业级ECIF系统的构建设计(未完工)

一:概念: 企业级客户信息系统.作为银行的一 个基础设施项目,承担整合银行各系统中 的客户信息,为其他应用系统提供客户信 息的任务.是银行的统一的客户数据源和 客户信息的数据交换中枢. 二:所需概念 ①:ETL入库加工 ②:ecif数据模型 ③:数据分析 三:目标 ①  建立整合的单一客户视图集群,在这里对客户的 全面信息进行取得. 记录. 修改等操作, 包括基本信 息. 各类帐户. 关系信息等, 构建企业统一的客 户单一视图. 归并和拆分客户信息. 并且处理原有业务系 统保留自身客户信息, 客

[读书笔记]普林斯顿微积分读本(修订版)-未完工

这本书比较厚.刚开始读.新的策略是一路读.一路记笔记. [前言] 拿到一本书,最好先看看前言.因为前言是作者在给你介绍写这本书的思路,也会向你传递你该如何使用这本书等信息,有时也会提及他写书的心路历程等等. 这本书的前言就讲到了读者可能提出的一些常见问题,以及作者写作本书的框架. 让我觉得有意思的是下面这些例图(摘自原书),因为后面读书时你就知道了哪里是例题,哪里非常重要,哪里要试着做一做,哪里可以暂时略过. 还有哪里需要背诵呢?你可以自己读读前言. 例题求解过程始于此行. 这里非常重要. 你应

javascript——正则表达式(RegExp、String)(未完工)

在 javascript 中,正则表达式由两部分组成:正则表达式的匹配模式文本:匹配模式文本的修饰符: 修饰符: 修饰符 说明 i 忽略大小写 g 执行全局匹配 m 执行多行匹配 匹配模式文本包括以下内容: 括号:查找某个范围内的字符: 表达式 说明 [abc] 符合括号中的任意一个即可 [^abc] 括号中的均不能出现 [0-9] 数字0-9均可 (red|blue|green) 符合三者之一 元字符:是拥有特殊含义的字符 元字符 描述 . 查找单个字符,除了换行和行结束符. \w 查找单词字

CTU Open 2008(未完工)

链接:CTU Open 2008 [2014/05/15]今晚做了一下CTU 2008的这套题,最后的rank是3道题.基本是水题啊,我们做的是4个小时,如果完整做,我想应该还会出掉D题,主要是D题很繁琐,weikd写起都说烦.   A - Alea iacta est B - On-Line Banking [题意]纯模拟题,模拟银行存钱,取钱,转钱的操作.注意下细节~: 1 #include <cstdio> 2 #include <cstring> 3 #include &l

Oracle——判断对象是否存在(未完工)

一.系统表: 1.User_Tables:存储用户下的所有表的信息: 2.dba_tables:存储管理员权限下的所有表的信息: 3.all_tables:存储所有表的信息. 二.判断对象是否存在 1.判断表 我们只能通过使用select count(*) 的方式判断当前表是否存在,返回1则代表存在,0则代表不存在,例如: SELECT COUNT(*) FROM User_Tables WHERE table_name = 'CODE_BMDM';(在SQL中使用这种方法亦可)需要注意的是:表

未清销售订单及预测的所有工序物料需求(按BOM展开不考虑已发料)

--按截止日考虑库存分配(所有物料及工序) DECLARE @dueDate DATETIME --截止交期 SELECT @dueDate = T0.T_DueDate FROM OFPR T0 WHERE T0.T_DueDate = [%0] SELECT @dueDate = '[%0]' --------------------------------------------------------------------------------------------- -- ===

关于成本核算方法、步骤、成本分析的简单回复

关于成本核算方法.步骤.成本分析的简单回复成本核算的方法依据企业生产产品的特点来定:主要看产品是否是多步骤生产(生产工艺的特点):半成品是否有销售的情况(假设有销售,可能须要採用分步核算,以便准确核算半成品的成本):工作(成本/生产)中心是依照产品来分还是工艺来分.怎样核算成本:首先归集产品的材料成本,一般都须要技术部门提供产品的BOM(物料清单),以确保按订单或者生产计划生产的时候领料的准确.(通常会问生产线出现来料不良和损坏怎么处理:退仓并补领就可以,损坏部分须要当月预提计入制费,损坏材料报