在这一章中,动态顺序统计和区间树被举例用来显示怎样去扩张一个数据结构。一般来说,扩张一个数据结构分为以下四个步骤:
当然设计一个数据结构的扩张,没有那么顺利,永远包含着试探和纠错。下面给出基于红黑树的动态顺序统计和区间树的代码。
下面代码给出了左旋,右旋,恢复插入引起的红黑树性质的破坏,插入,恢复删除引起的红黑树性质的破坏,删除,查找第i小关键字,返回一个元素的秩。
template<class Type>
void orderStatisticTree<Type>::leftRotate(node* x)
{
node* y=x->right;
y->parent=x->parent;
if(x->parent==nullNode)
root=y;
else if(x==x->parent->left)
x->parent->left=y;
else
x->parent->right=y;
x->right=y->left;
if(y->left!=nullNode)
x->right->parent=x;
y->left=x;
x->parent=y;
//上面代码和红黑树右旋代码一样,下面两行代码用来维护附加信息size。
y->size=x->size;
x->size=x->left->size+x->right->size+1;
}
template<class Type>
void orderStatisticTree<Type>::rightRotate(node* x)
{
node* y=x->left;
y->parent=x->parent;
if(x->parent==nullNode)
root=y;
else if(x==x->parent->left)
x->parent->left=y;
else
x->parent->right=y;
x->left=y->right;
if(y->right!=nullNode)
x->left->parent=x;
y->right=x;
x->parent=y;
//上面代码和红黑树右旋代码一样,下面两行代码用来维护附加信息size。
y->size=x->size;
x->size=x->left->size+x->right->size+1;
}
这代码和红黑树那一章的代码一样。
template<class Type>
void orderStatisticTree<Type>::RBInsertFixup(node* currentNode)
{
while(currentNode->parent->color==RED){
if(currentNode->parent==currentNode->parent->parent->left){
node* uncleNode=currentNode->parent->parent->right;
if(uncleNode->color==RED){
currentNode->parent->color=BLACK;
uncleNode->color=BLACK;
currentNode->parent->parent->color=RED;
currentNode=currentNode->parent->parent;
}
else if(currentNode==currentNode->parent->right){
currentNode=currentNode->parent;
leftRotate(currentNode);
}
else{
currentNode->parent->color=BLACK;
currentNode->parent->parent->color=RED;
rightRotate(currentNode->parent->parent);
}
}
else {
node* uncleNode=currentNode->parent->parent->left;
if(uncleNode->color==RED){
currentNode->parent->color=BLACK;
uncleNode->color=BLACK;
currentNode->parent->parent->color=RED;
currentNode=currentNode->parent->parent;
}
else if(currentNode==currentNode->parent->left){
currentNode=currentNode->parent;
rightRotate(currentNode);
}
else{
currentNode->parent->color=BLACK;
currentNode->parent->parent->color=RED;
leftRotate(currentNode->parent->parent);
}
}
}
root->color=BLACK;
}
template<class Type>
void orderStatisticTree<Type>::insert(const Type& val)
{
node* currentNode=root;
node* prevNode=nullNode;
while(currentNode!=nullNode){
currentNode->size+=1;//从根到新插入点路径上的各个结点size加1。
prevNode=currentNode;
if(val<currentNode->key)
currentNode=currentNode->left;
else
currentNode=currentNode->right;
}
if(prevNode==nullNode)
root=new node(val,1,nullNode,nullNode,nullNode,BLACK);
else if(val<prevNode->key){
prevNode->left=new node(val,1,prevNode,nullNode,nullNode,RED);
RBInsertFixup(prevNode->left);
}
else{
prevNode->right=new node(val,1,prevNode,nullNode,nullNode,RED);
RBInsertFixup(prevNode->right);
}
}
template<class Type>
void orderStatisticTree<Type>::RBRemoveFixup(node* currentNode)
{
node* tmp=currentNode->parent;
while(tmp!=nullNode){
tmp->size=tmp->left->size+tmp->right->size+1;
tmp=tmp->parent;
}//将currentNode到根路径上的各个节点size减1。
while(currentNode!=root&¤tNode->color==BLACK){
if(currentNode==currentNode->parent->left){
node* brotherNode=currentNode->parent->right;
if(brotherNode->color==RED){
brotherNode->color=BLACK;
currentNode->parent->color=RED;
leftRotate(currentNode->parent);
}
else if (brotherNode->left->color==BLACK&&brotherNode->right->color==BLACK){
brotherNode->color=RED;
currentNode=currentNode->parent;
}
else if(brotherNode->right->color==BLACK){
brotherNode->left->color=RED;
brotherNode->color=RED;
rightRotate(brotherNode);
brotherNode=currentNode->parent->right;
}
else{
brotherNode->color=currentNode->parent->color;
currentNode->parent->color=BLACK;
leftRotate(currentNode->parent);
currentNode=root;
}
}
else{
node* brotherNode=currentNode->parent->left;
if(brotherNode->color==RED){
brotherNode->color=BLACK;
currentNode->parent->color=RED;
rightRotate(currentNode->parent);
}
else if (brotherNode->right->color==BLACK&&brotherNode->left->color==BLACK){
brotherNode->color=RED;
currentNode=currentNode->parent;
}
else if(brotherNode->left->color==BLACK){
brotherNode->right->color=RED;
brotherNode->color=RED;
leftRotate(brotherNode);
brotherNode=currentNode->parent->left;
}
else{
brotherNode->color=currentNode->parent->color;
currentNode->parent->color=BLACK;
rightRotate(currentNode->parent);
currentNode=root;
}
}
}
currentNode->color=BLACK;
}
代码和红黑树中删除代码一样。
template<class Type>
void orderStatisticTree<Type>::transplant(node* u,node* v)
{
if(u->parent==nullNode)
root=v;
else if(u==u->parent->right)
u->parent->right=v;
else
u->parent->left=v;
v->parent=u->parent;
}
template<class Type>
bool orderStatisticTree<Type>::remove(const Type& val)
{
node* searchNode=search(val,root);
if(searchNode==nullNode)
return false;
int originalColor;
node* x=0;
if(searchNode->left==nullNode){
x=searchNode->right;
transplant(searchNode,searchNode->right);
originalColor=searchNode->color;
}
else if(searchNode->right==nullNode){
x=searchNode->left;
transplant(searchNode,searchNode->left);
originalColor=searchNode->color;
}
else{
node* succNode=findMinimum(searchNode->right);
originalColor=succNode->color;
x=succNode->right;
if(succNode->parent==searchNode)
x->parent=succNode;
else{
transplant(succNode,succNode->right);
succNode->right=searchNode->right;
succNode->right->parent=succNode;
}
transplant(searchNode,succNode);
succNode->left=searchNode->left;
succNode->color=searchNode->color;
succNode->size=searchNode->size;
}
delete searchNode;
if(originalColor==BLACK)
RBRemoveFixup(x);
return true;
}
//返回第i小的元素:
template<class Type>
const Type& orderStatisticTree<Type>::select(int i) const
{
node* currentNode=root;
int rank=currentNode->left->size+1;
while(rank!=i){
if(i<rank)
currentNode=currentNode->left;
else{
currentNode=currentNode->right;
i=i-rank;
}
rank=currentNode->left->size+1;
}
return currentNode->key;
}
template<class Type>
int orderStatisticTree<Type>::rank(const Type& val) const
{
node* searchNode=search(val,root);
if(searchNode==nullNode)
throw runtime_error("the element is not existent in the tree.");
int rank=searchNode->left->size+1;
node* currentNode=searchNode;
while(currentNode!=root){
if(currentNode==currentNode->parent->right)
rank+=currentNode->parent->left->size+1;
currentNode=currentNode->parent;
}
return rank;
}