SBTree树实现
SBTree与AVL树具有相同的概念,也具有相同的操作,类似自平衡,旋转操作和旋转触发。SBTree严格遵守下列公式,如有违反,则需要通过相应的转置操作来达到平衡.
SIZE[right[t]] >= max(SIZE[left[left[t]]],SIZE[right[left[t]]]);
SIZE[left[t]] >= max(SIZE[left[right[t]]],SIZE[right[right[t]]]);
其中SIZE[t]表示t结点所在的子树个数,且两个公式必须同时满足
SIZE[left[left[t]]]可以表示成t->left->left,SIZE[right[left[t]]]可表示成t->left->right
每个结点所在子树的结点个数不小于其兄弟的两个孩子所在子树的结点个数。
还有SBTree只有在插入时才可能触发调整.
下面看其实现:
#include <iostream>using namespace std;//树节点类class SBTNode{//size:子树大小,就是以当前节点为根构成的树有多少节点//data:权值,就是树上的节点存储的值//value:临时存储权值的int data,size,value;SBTNode *lchild,*rchild,*father;//构造函数,参数分别为权值,以当前节点为根的树的大小,父亲节点SBTNode(int init_data,int init_size = 0,SBTNode *init_father = NULL);~~SBTNode();//二叉排序树的插入void insert(SBTNode *node,int value);//搜索SBTNode *search(int value);//找前驱SBTNode *predecessor();//找后继SBTNode *successor();//移除某个度为0或1的节点void remove_node(SBTNode *delete_node);//移除某个权值的点bool remove(int value);//找出第k大的元素int select(int k);};class BinaryTree{
private:SBTNode *root;
public:BinaryTree();~BinaryTree();//下面依次是二叉树的插入、查找、删除节点、找出第k大的树,都是以上面//的节点类的函数为基础的void insert(int value);bool find(int value);bool remove(int value);int select(int k);
};
//这里搞了个权值为0的节点,就相当于我们的NULL
//不过我们这里代替NULL指针的是ZERO(权值为0的节点)的地址,我们看到下面SBTNode的构造函数初始化的时候用的也是ZPTR指针.SBTNode ZERO(0);
SBTNode* ZPTR = &ZERO;SBTNode::SBTNode(int init_data,int init_size,SBTNode *init_father){data = init_data;size = init_size;lchild = ZPTR;rchild = ZPTR;father = init_father;
}SBTNode::~SBTNode(){if(lchild != ZPTR){delete lchild;}if(rchild != ZPTR){delete rchild;}
}//左旋:将右孩子变为“根节点”(当前子树的根节点),右孩子的左孩子变为原来根节点的右孩子
//下面注释中:node(原来的根节点)的右孩子用“根节点”来说
SBTNode *left_rotate(SBTNode *node){//用temp保存“根节点”SBTNode *temp = node->rchild;//"根节点"的左孩子 变为node(原来的根节点)的右孩子node->rchild = temp->lchild;//更新"根节点"原来的左孩子的父亲为node(原来的根节点)temp->lchild->father = node;//node(原来的根节点)就变为"根节点"的左孩子temp->lchild = node;//"根节点"的父亲更新为node(原来的根节点)的父亲temp->father = node->father;//node(原来的根节点)的父亲更新为"根节点"node->father = temp;//"根节点"的大小更新为node(原来的根节点)的大小temp->size = node->size;//node(原来的根节点)的大小更新为它左孩子和右孩子的大小再加上本身1node->size = node->lchild->size + node->rchild->size + 1;//返回左旋后的根节点return temp;
}//右旋:将左孩子变为"根节点"(当前子树的根节点),左孩子的右孩子就变为原来的根节点的左孩子
//下面注释中:node(原来的根节点)的左孩子用"根节点"来说
SBTNode *right_rotate(SBTNode *node){//用temp保存"根节点"SBTNode *temp = node->lchild;node->lchild = temp->rchild;temp->rchild->father = node;temp->rchild = node;temp->father = node->father;node->father = temp;temp->size = node->size;node->size = node->lchild->size + node->rchild->size + 1;return temp;
}//利用上面的左右旋进行调整的函数
//flag为false:处理左子树更高得情况,否则处理右子树更高得情况
//node:要调整的子树的根节点
SBTNode *maintain(SBTNode *node,bool flag){//左子树比右子树高if(flag == false){//LL型:左子树的左子树的元素个数大于右子树的元素个数,应进行右旋if(node->lchild->lchild->size > node->rchild->size){//右旋并更新子树的根节点node = right_rotate(node);}//LR型:左子树的右子树的元素个数大于右子树的元素个数//那么先对左子树进行左旋,就变成了LL型,再右旋即可else if(node->lchild->rchild->size > node->rchild->size){//左旋并更新左子树的根节点node->lchild = left_rotate(node->lchild);//右旋并更新根节点node = right_rotate(node);}else{//说明平衡了,返回根节点return node;}}//右子树比左子树高else{//RR型:右子树的右子树的元素大于左子树的元素个数,应进行左旋if(node->rchild->rchild->size > node->lchild->size){//左旋并更新根节点node = left_rotate(node);}//RL型:右子树的左子树的元素个数大于左子树的元素个数//那么先对右子树进行右旋,变成RR型,再左旋即可.else if(node->rchild->lchild->size > node->lchild->size){//右旋并更新左子树的根节点node->rchild = right_rotate(node->rchild);//左旋并更新根节点node = left_rotate(node);}else{//说明平衡了,返回根节点return node;}}//下面为递归调用,因为有时上面的调整过后,左子树和右子树的某个节点还是不平衡//递归调用,处理可能左子树的左子树更高的情况//false表示左子树较高node->lchild = maintain(node->lchild,false);//其右子树的右子树高度更高的情况node->rchild = maintain(node->rchild,true);//最后再对子树根节点的左右子树递归进行调整node = maintain(node,false);node = maintain(node,true);//返回调整后的子树的根节点return node;
}SBTNode *insert(SBTNode *node,int value){if(value == node->data){return node;}else{node->size++;if(value > node->data){if(node->rchild == ZPTR){node->rchild = new SBTNode(value,1,node);}else{node->rchild = insert(node->rchild,value);}}else{if(node->lchild == ZPTR){node->lchild = new SBTNode(value,1,node);}else{node->lchild = insert(node->lchild,value);}}}return maintain(node,value > node->data);
}SBTNode *SBTNode::search(int value){if(data == value){return this;}else if(value > data){if(rchild == ZPTR){return ZPTR;}else{return rchild->search(value);}}else{if(lchild == ZPTR){return ZPTR;}else{return lchild->search(value);}}
}SBTNode *SBTNode::predecessor(){SBTNode *temp = lchild;while(temp != ZPTR && temp->rchild != ZPTR){temp = temp->rchild;}return temp;
}SBTNode *SBTNode::successor(){SBTNode *temp = rchild;while(temp != ZPTR && temp->lchild != ZPTR){temp = temp->lchild;}return temp;
}void SBTNode::remove_node(SBTNode *delete_node){SBTNode *temp = ZPTR;if(delete_node->lchild != ZPTR){temp = delete_node->lchild;temp->father = delete_node->father;delete_node->lchild = ZPTR;}if(delete_node->rchild != ZPTR){temp = delete_node->rchild;temp->father = delete_node->father;delete_node->rchild = ZPTR;}if(delete_node->father->lchild == delete_node){delete_node->father->lchild = temp;}else{delete_node->father->rchild = temp;}temp = delete_node;while(temp != NULL){temp->size--;temp = temp->father;}delete delete_node;
}bool SBTNode::remove(int value){SBTNode *delete_node, *current_node;current_node = search(value);if(current_node == ZPTR){return false;}size--;if(current_node->lchild != ZPTR){delete_node = current_node->predecessor();}else if(current_node->rchild != ZPTR){delete_node = current_node->successor();}else{delete_node = current_node;}current_node->data = delete_node->data;remove_node(delete_node);return true;
}int SBTNode::select(int k){//rank当前节点在子树的排位int rank = lchild->size + 1;//若rank等于第k大,说明就是要找的值,直接返回权值if(rank == k){return data;}else if(k < rank>){//小于rank,就表明要找比当前节点更小的值,就在左边查找return lchild->select(k);}else{//大于就在右边//这里只所以看k-rank,因为我们已经把前rank排除了,//相当于我们要在右子树(把他当做一棵新的树去查找),所以排位当然要减去rank.return rchild->select(k - rank);}
}BinaryTree::BinaryTree(){root = NULL;
}BinaryTree::~BinaryTree(){if(root != NULL){delete root;}
}void BinaryTree::insert(int value){if(root == NULL){//初始化时只有根节点,所以子树大小为1root = new SBTNode(value,1);}else{root = ::insert(root,value);}
}bool BinaryTree::find(int value){if(root->search() == NULL){return false;}else{ return true;}
}bool BinaryTree::remove(int value){return root->remove(value);
}int BinaryTree::select(int k){return root->select(k);
}