4个步骤:
-
选择一种基础数据结构
-
确定基础数据结构中要维护的附加信息
-
检查基础数据结构上一些操作是否需要维护附加信息
-
为附加信息添加一些新的操作
2 举例
扩展红黑树(或是其他树),能够在O(lgn)内获取第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
}
}
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+1,添加以后,自己的size=1,O(lgn) -
旋转,以左旋为例: 原先父节点pre,旋转以后父节点cur
新的父节点的size等于原先父节点的size.(因为元素个数没变)
原先父节点的个数变为
pre->size=pre->left->size+cur->right->size+1
删除过程:
-
删除操作,遍历路径从根节点到节点
replace_node,路径上所有节点size-1 -
旋转,同插入