ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

笛卡尔树

2022-01-19 23:32:33  阅读:156  来源: 互联网

标签:笛卡尔 top 元素 栈顶 stk 儿子


笛卡尔树

定义:笛卡尔树是一种二叉树,每一个结点由一个键值二元组 \((k,w)\) 构成。要求 \(k\) 满足二叉搜索树的性质,而 \(w\) 满足堆的性质。一个有趣的事实是,如果笛卡尔树的 \((k,w)\) 键值确定、并且 \(k\) 不相同, \(w\) 不相同,那么这个笛卡尔树的结构是唯一的。


建树方法:

给定一个序列A,下面建树的过程中以小根堆为例,定义序列中第 \(i\) 个元素的键值为 \((i,A_i)\) ,也就是 \(i\) 对应 \(k\) ,\(A_i\) 对应 \(w\) ,我们要求 \(k\) 满足二叉搜索树的性质,那么此时我们进行思考,我们每插入一个新的点,由于 \(k\) 必然是递增关系,所以这个新点的 \(k\) 比上一个点大,这个时候我们能确定,这两个点的关系必然是 \(k-1\) 点是 \(k\) 点的左儿子或者 \(k\) 点是 \(k-1\) 点的右儿子,直接和上一次的点比较 \(w\) 即可,如果后来的 \(w\) 大,就直接成为前一个的右儿子,同时也和下面的右儿子比较一下,看看符不符合这个关系,不然的话,成为前一个的父亲,同时与上方的父亲进行比较,继续判断是否交换

我们发现,上述操作维护的都是原节点的右链,所以我们可以选择直接处理

实现方法:每个数只会进出右链一次,这个过程我们用栈维护,如果一个数不在右栈上的话就弹出,栈中维护当前笛卡尔树的右链上的结点,复杂度 \(O(n)\)


rep(i, 1, n){
    int k = top;
    while (k && h[stk[k]] > h[i]) k--;
    if (k) rs[stk[k]] = i;  // rs代表笛卡尔树每个节点的右儿子
    if (k < top) ls[i] = stk[k+1];  // ls代表笛卡尔树每个节点的左儿子
    stk[++k] = i;
    top = k;
}
新建一个大小为 n 的空栈。用 top 来标操作前的栈顶,k 来标记当前栈顶。
For i := 1 to n
    k := top
    While 栈非空 且 栈顶元素 > 当前元素 
        k--
    if 栈非空
        栈顶元素.右儿子 := 当前元素
    if k < top
        当前元素.左儿子 := 栈顶元素
    当前元素入栈
    top := k

标签:笛卡尔,top,元素,栈顶,stk,儿子
来源: https://www.cnblogs.com/RevolutionBP/p/15824637.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有