首先给出数据结构的扩张的四个步骤:
1)选择基础的数据结构;
2)确定要在基础数据结构中添加哪些信息;
3)验证可以用基础数据结构上的基本修改操作来维护这些新添加的信息;
4)设计新的操作。
算法导论书上给出的是红黑树的一种扩张-动态顺序统计。
将容量为n的随机样本的各个测定值 (x1,x2,……,xn),从小到大顺序的排列,xi所在的顺序位置就是它的顺序统计量。
动态顺序统计是指,在一个动态的无序的集合中,任意的顺序统计量都可以在O(lgn)时间内确定(线性的结构需要O(n)的时间)。
至于扩展红黑树,最终要的一点就是扩展之后操作已经新域的维护都可以控制在原复杂度内。
扩展步骤如下(c++实现):
1.在红黑树的成员中添加一个int型的size变更。
class BRTreeNode { private: friend class BRTree; int key; int size; bool color; BRTreeNode* left; BRTreeNode* right; BRTreeNode* parent; }2.维护数据域,主要有左旋,右旋。
//左旋节点node bool LeftRotate(BRTreeNode* node) { BRTreeNode*y; if(node->right==nil) { cout<<"can't left rotate!"<3.定义新的操作right; node->right=y->left; if(y->left!=nil) { y->left->parent=node; } y->parent=node->parent; if(node->parent==nil) { root=y; } else if(node->parent->left==node) { node->parent->left=y; } else { node->parent->right=y; } y->left=node; node->parent=y; //维护size域 y->size=node->size; node->size=node->left->size+node->right->size+1; return 1; } //右旋节点 bool RightRotate(BRTreeNode* node) { if(node->left==nil) { cout<<"can't rightrotate!"< left; node->left=x->right; if(x->right!=nil) { x->right->parent=node; } x->parent=node->parent; if(node->parent==nil) { root=x; } else if(node->parent->left==node) { node->parent->left=x; } else { node->parent->right=x; } node->parent=x; x->right=node; //维护size域 node->size=x->size; x->size=x->left->size+x->right->size+1; return 1; }
1)先根遍历
void Preorder(BRTreeNode*node) { if(node!=nil) { cout<2)查找树中第num小的顺序统计量key<<" "<<"size:"< size<<" "; Preorder(node->left); Preorder(node->right); } }
BRTreeNode* GetIthnode(BRTreeNode*node,int num) { int r=node->left->size+1; if(r==num) { cout<<"Got it!"<3)确定树中某个以k为key值的元素的秩key< num) { return GetIthnode(node->left,num); } else { return GetIthnode(node->right,num-r); } }
int getRank(BRTreeNode*node,int key) { int r=node->left->size+1; int k=node->key; if(k==key) { return r; } else if(key最后来测试一下:left,key)-1; } else { return r+getRank(node->right,key); } }
int mian() { BRTree tree; tree.init(); cout<<"Insert 8 numbers:"<运行结果:
其余的操作可以参考之前的一片文章:
参考:
《算法导论》第二版