1 如何做数据扩张
4个步骤:
- 选择一种基础数据结构
- 确定基础数据结构中要维护的附加信息
- 检查基础数据结构上一些操作是否需要维护附加信息
- 为附加信息添加一些新的操作
2 举例
扩展红黑树(或是其他树),能够在O(lgn)内获取第i小的元素.
为每个节点添加一个size
成员变量,表示当前节点所有子节点的个数+1,加1是因为自己还有一个.因此:
pre->size=pre->left->size+pre->right->size+1;
要想找到第i小的元素
RBNode* RBTree::find(size_t i) { return axu_find(mp_root,i); } RBNode* RBTree::aux_find(RBNode* cur,size_t i) { size_t index = cur->left->size+1;//当前节点在书中的序号,秩 if(index==i) { return cur; }else if(index < i){ //i还有在 cur 的后面 return aux_find(cur->right,i-r);// i-r 表示,之前已经有r个了,再往后找i-r个就是了 }else if(index > i){ // i 在 cur 的前面 return aux_find(cur->left); // 没有跳过任何元素,因此直接传 i } }
相对应的,也可以找到第i大的元素,也就是根节点size-i+1
小的元素.
确定一个节点在树中的是第几小的.
size_t* RBTree::find(RBNode *node) { size_t index = node->left->size+1; // 这只是自己统治下节点的排序. RBNode* pre = node; while(pre != mp_root) { //只有自己是一个右节点的时候,才要加上左节点的元素数目,如果不是,就不加. if(pre == pre->p->right) { r=r+pre->p->left->size+1; //自己父节点的右子树个数 + 父节点的1 } pre = pre->p; //向上递归,直到p是根节点. } }
size的维护
插入过程:
- 添加元素时,所有元素途径的路径上
size+1
,添加以后,自己的size=1
,O(lgn) - 旋转,以左旋为例: 原先父节点pre,旋转以后父节点cur
新的父节点的size等于原先父节点的size.(因为元素个数没变)
原先父节点的个数变为
pre->size=pre->left->size+cur->right->size+1
删除过程:
- 删除操作,遍历路径从根节点到节点
replace_node
,路径上所有节点size-1
- 旋转,同插入
原文地址:https://www.cnblogs.com/perfy576/p/8665672.html
时间: 2024-11-08 22:43:10