笛卡尔树
笛卡尔树是一种同时满足二叉搜索树和堆的性质的数据结构. 可以在一个数组上构造出来(时间复杂度可以达到 O(n) O ( n ) ). 树中节点有几个属性, key(节点元素的大小, 优先级priority), index(节点在元素组中的索引), left(左子节点), right(右子节点), parent(父节点).
性质
- 树中的元素满足二叉搜索树性质, 树的中序遍历得到的序列为原数组序列;
- 树中节点满足堆性质, 节点的==key==值要大于其左右子节点的key值.
构造
要求在给定的数组的基础上构造一颗笛卡尔树, 这可以在 O(n) O ( n ) 的时间内完成. 其具体思路为:
当按照index从1到n(或者从0到n - 1)的顺序将数组中的每个元素插入到笛卡尔树中时, 当前要被插入的元素的index值最大, 因此根据二叉搜索树的性质, 需要在当前已经完成的笛卡尔树的根的右子树中进行搜索.
由于笛卡尔树要满足堆的性质(以大根堆为例), 父节点的key值要大于子节点的key值, 所以沿着树根的右子树往下走, 直到遇到的节点的key值小于等于当前要插入节点的key值.
此时, 便找到了当前节点需要插入的位置, 记为 P P . 此时下方的节点的key值肯定小于当前要插入的节点的key, index也小于当前要插入的节点的index.
所以在讲当前节点插入到P的位置后, 把以P为根的子树挂到当前已经插入的节点的左子树上.
实际实现时, 可采用栈. 栈中保存当前树中从root开始的右子节点链, root在栈底.
插入新元素的时候, 从树的右子链的最末尾从下往上查找, 直到找到第一个满足堆性质的节点(即找到的节点的key值大于当前需要插入的节点). 用栈来实现就是从栈顶不断弹出元素, 直到栈顶的元素的key大于当前节点的key, 然后将该节点入栈, 同时将最后被弹出的节点的parent指向该节点, 以及该节点的左子节点指向最后弹出的节点.