二叉搜索树(BST)
BST定义
- 所有的关键字只能出现一遍
- 左子树所有节点的关键值小于根节点,右子树所有节点的关键值大于根节点
- 左右子树也都是二叉搜索树 ➡️递归
索引二叉搜索树
- 每个节点记录一个索引值(左子树大小+1)➡️节点在以它为根的子树中的排名
- 如何找到第k元?
- 如何确定一个节点的关键值是整棵树的第几大?
template<class E, class K>
class BSTree : public BinaryTree<E> { //由二叉树派生
public:
bool Search(const K& k, E& e) const;
BSTree<E,K>& Insert(const E& e);
BSTree<E,K>& Delete(const K& k, E& e);
void Ascend() {InOutput();} //升序输出:中序遍历
};
BST搜索
算法
- 从根节点开始将key与节点值比较
- 如果key小于节点值,进入左子树,如果大于节点值,进入右子树
- 递归,直到找到或子树为空停止
平均查找长度
- 成功:(需要比较找到节点的次数*同一层有几个节点)的累加和除总节点数
- 失败:(需要比较确认搜索失败的次数*同一层有几个空子树)的累加和除总空子树
搜索函数: O(log n)~O(n)
template<class E, class K>
bool BSTree<E,K>::Search(const K& k, E &e) const {
BinaryTreeNode<E> *p = root;
while (p)
if (k < p->data)
p = p->LeftChild;
else if (k > p->data)
p = p->RightChild;
else {
e = p->data;
return true;
}
return false;
}
BST插入
算法
- 先进行搜索操作
- 若成功,表明有重复关键字,插入失败
- 若失败,搜索结束的位置即为插入位置
- 新插入的节点一定是一个叶子节点
插入函数: O(log n)~O(n)
template<class E, class K>
BSTree<E,K>& BSTree<E,K>::Insert(const E& e) {
BinaryTreeNode<E> *p = root, //搜索指针
*pp = 0; //搜索指针的父指针
while (p) { //找到应该插入的位置
pp = p;
if (e < p->data)
p = p->LeftChild;
else if (e > p->data)
p = p->RightChild;
else //关键值重复
throw BadInput();
}
BinaryTreeNode<E> *r = new BinaryTreeNode<E> (e);
if (root) { //如果树不为空
if (e < pp->data)
pp->LeftChild = r;
else
pp->RightChild = r;
}
else //如果树为空
root = r;
return *this;
}
BST删除
算法
- 删除叶节点:直接丢弃,即将父节点指向它的指针置零
- 删除有且仅有一个非空子树的节点:丢弃节点,其子树取代它原来的位置
- 删除有两个非空子树的节点:节点的左子树中最大的元素或右子树中最小的元素替代它
删除函数: O(log n)~O(n)
template<class E, class K>
BSTree<E,K>& BSTree<E,K>::Delete(const K& k, E& e){
BinaryTreeNode<E> *p = root, //搜索指针
*pp = 0; //搜索指针的父指针
while (p && p->data != k) {
pp = p;
if (k < p->data)
p = p->LeftChild;
else
p = p->RightChild;
}
if (!p) //如果不存在
throw BadInput();
e = p->data;
if (p->LeftChild && p->RightChild) { //如果两个子树均不为空
BinaryTreeNode<E> *s = p->LeftChild,
*ps=p;
while (s->RightChild) { //找到左子树里的最大节点(最右)
ps = s;
s = s->RightChild;
}
p->data = s->data; //交换两个节点
p = s;
pp = ps;
}
//最多只有一个子树
BinaryTreeNode<E> *c;
if (p->LeftChild)
c = p->LeftChild;
else
c = p->RightChild;
if (p == root)
root = c;
else {
if (p == pp->LeftChild)
pp->LeftChild = c;
else
pp->RightChild = c;
}
delete p;
return *this;
}
缺陷
- 仅对树节点的大小关系做出约束,而没有对树高做出约束
- 树越高,搜索、插入、删除的性能越差
平衡二叉搜索树(AVL)
AVL定义
- AVL是特殊的BST
- 左子树和右子树是AVL树 ➡️递归
- 左子树和右子树的树高差不超过1 ➡️对树高做出约束
- 空二叉树是AVL树
AVL树的描述
- 平衡因子bf=左子树高度-右子树高度
AVL搜索(同BST)
AVL插入
算法
- 利用BST的插入算法,先把数据插入
- 如果出现不平衡的情况,即平衡因子,则调整结构
- 追踪从根节点到插入位置路径上的节点,原来平衡因子的节点有可能不平衡
- 如果出现不平衡,新节点一定是插入了本来较高的子树,找到离新节点最近的不平衡节点,如果插入左子树的左子树,则称为LL型
- LL型不平衡及其调整方法
- LR型不平衡及其调整方法
AVL删除
算法
- 利用BST的删除操作,先把数据删除
- 如果出现不平衡的情况,即平衡因子,则调整结构
- 如果出现不平衡,一定是在本来较矮的子树上删除了一个节点,找到离删除节点最近的不平衡节点,如果删除了其右子树,其左子树的平衡因子为0,则成为R0型
- R0型不平衡的调整,处理完后局部高度未变,祖先平衡因子不需要调整
- R1型不平衡的调整,处理完后局部高度-1,需要往上继续修正
- R-1型不平衡的调整,处理完后局部高度-1,需要往上继续修正
B树
动机:建立索引
m叉搜索树
定义
- 在相应的扩充搜索树中(用外部节点替换零指针),每个内部节点最多可以有m个子女及m-1个元素(外部节点不含元素和子女)
- 每个含p个元素的节点,有p+1个子女
- 每个节点内部元素升序排列,子女的大小界在父节点相应的元素之间
搜索
- 从根节点开始向下搜索
- 对每个节点,如果能找到关键字,搜索成功,如果关键字的大小在节点内的两个元素之间,在子树中继续寻找
- 如果到达外部节点,则搜索失败
插入
- 先进行搜索操作,如果成功则插入失败(关键值不能重复)
- 如果失败,在失败的位置进行插入,如果能够在同级插入就插入,保持树尽量扁平
删除
- 先进行搜索操作,如果失败则删除失败
- 左右子树均为空,直接进行删除
- 左右子树不都为空,子树中元素提升,替代被删除的元素
高度
- 高度为,最少个元素,最多
- 个元素,高度
m阶的B树
定义
- 是m叉搜索树
- 根节点至少有2个孩子
- 除根节点外,所有内部节点至少有个孩子(取上界)
- 所有外部节点位于同一层上 ➡️方便数据库的索引
高度
- 设T是一棵高度为h的m阶B树,d= 且n是T中的元素个数,则
插入操作
- 先进行搜索操作,如果可以在同一层插入,则插入
- 如果同一层满了,先插入,再把这棵子树分裂成两棵,把最中间的元素提上去
删除操作
- 删除叶节点中元素,能借就借,不能借就合并
- 如果不符合最小元素的数目,和兄弟节点借一个
- 如果大小关系不符合,向父节点借一个
- 如果借不了,就合并
- 删除非叶节点元素,类似AVL树,子树叶节点元素与之交换
B+树
定义
- 所有有效的关键字都放在叶节点中,上层的非叶节点的关键字是其子树中最大关键字的拷贝
- 叶节点包含了全部关键字,且叶节点本身按关键字值从小到大链接
- 一个叶节点可以有m个元素
插入操作
- 通过查找,在叶节点的适当位置插入
- 如果插入后不符合定义,将该叶节点均匀分裂,更新其父节点
- 递归检查其父节点在更新后是否满足定义
删除操作
- 删除叶节点
- 如果不满足最小元素的要求,从兄弟节点借一个
- 如果借不了,合并兄弟节点
- 递归检查父节点是否满足定义
红黑树
定义
- 特殊的二叉扩充搜索树
- 根节点和所有外部节点的颜色是黑的
- 根节点到外部节点的路径上没有连续红节点
- 所有根到外部节点的路径具有相同数目的黑节点
- 节点的阶:从该节点到其子树中任一外部节点的路径上的黑色指针数目
2-3-4树的红黑树表示
红黑树特性
- 若P、Q是红黑树中两条从根至外部节点的路径,那么
- 设h是一棵红黑树的高度( 不包括外部节点),n是树中内部节点的数目,而r是根节点的阶
插入操作
- 先进行二叉搜索树的插入方法
- 新节点应该是红色
- 如果出现连续红边,要调整树的结构,参考2-3-4树的插入操作。看祖父的另一个孩子是什么颜色:
- XYb(如果2-3-4树中节点没有挤爆):旋转变色,根黑子红
- XYr(如果2-3-4树中节点被挤爆了):不转变色,根红子黑
删除操作
- 删除非叶节点的,与中序遍历的后继节点交换
- 删除叶节点,如果是红节点,结束
- 如果是黑节点,调整结构
作业8
- 计算AVL树的高度
- 返回离AVL树根节点最近的值
// 13 5 2 8 7 9 23 77 0 12
template<typename T>
class AVLtree;
template<typename T>
class treeNode {
friend AVLtree<T>; //声明友元
public:
treeNode(){
parent=leftchild=rightchild=NULL;
h=0;
}
treeNode(const T& t){
data=t;
parent=leftchild=rightchild=NULL;
h=1;
}
private:
T data;
int h; //记录节点的高度
treeNode<T> *parent;
treeNode<T> *leftchild;
treeNode<T> *rightchild;
};
template<typename T>
class AVLtree {
public:
AVLtree(){
root=NULL;
}
int height(){ //树的高度即根节点的高度
if(root)
return root->h;
else
return 0;
}
treeNode<T>* find(T& t){ //找到应该插入的位置的父节点
treeNode<T> *p=root,*pp=NULL; //p为应该插入的位置,pp为p的父节点
while(p){
pp=p;
if(t<p->data) //如果关键值比当前节点的关键值小,进入左子树
p=p->leftchild;
else if(t>p->data) //如果关键值比当前节点的关键值大,进入右子树
p=p->rightchild;
else{ //如果关键值等于当前节点的关键值
pp=NULL;
break;
}
}
return pp;
}
AVLtree<T>& insert(T &t){ //插入关键值
treeNode<T> *p=find(t); //找到应该插入的位置的父节点
treeNode<T> *q=new treeNode<T>; //新建节点
q->data=t;
q->h=1;
q->parent=p;
if(!p){ //如果父节点为空
if(root){ //树不为空,说明关键值重复
cout<<"Data exists!"<<endl;
}
else{ //树为空
root=q;
}
return *this;
}
if(t<p->data) //如果关键值小于父节点的值
p->leftchild=q;
else //如果关键值大于父节点的值
p->rightchild=q;
if(p->rightchild==NULL||p->leftchild==NULL){ //如果父节点原来没有孩子,高度变化
p->h++;
while(p->parent&&(p->parent->h-p->h)!=1){ //往上寻找,更新高度
p=p->parent;
p->h++;
}
}
while(q->parent){ //从新节点往上寻找,是否有违反AVL树定义的节点
q=q->parent;
int lh,rh;
if(q->leftchild)
lh=q->leftchild->h;
else
lh=0;
if(q->rightchild)
rh=q->rightchild->h;
else
rh=0;
if((lh-rh)==2||(rh-lh)==2){ //如果失衡
treeNode<T> *s=q->parent;
int type;
if(!s)
type=0;
else if(s->leftchild==q)
type=1;
else
type=2;
if((lh-rh)==2){ //左子树失衡
if(q->leftchild->leftchild)
lh=q->leftchild->leftchild->h;
else
lh=0;
if(q->leftchild->rightchild)
rh=q->leftchild->rightchild->h;
else
rh=0;
if(lh>rh) //LL型
q=LLrotation(q);
else //LR型
q=LRrotation(q);
}
else if((rh-lh)==2){ //右子树失衡
if(q->rightchild->leftchild)
lh=q->rightchild->leftchild->h;
else
lh=0;
if(q->rightchild->rightchild)
rh=q->rightchild->rightchild->h;
else
rh=0;
if(lh>rh) //RL型
q=RLrotation(q);
else //RR型
q=RRrotation(q);
}
//以上只改变了q指向的位置,要把q在树中的位置也更新!!
if(type==0)
root=q;
else if(type==1)
s->leftchild=q;
else if(type==2)
s->rightchild=q;
//调整结构之后,往上寻找,更新节点的高度
while(s){
if(s->leftchild)
lh=s->leftchild->h;
else
lh=0;
if(s->rightchild)
rh=s->rightchild->h;
else
rh=0;
s->h=(lh>rh)? lh+1:rh+1;
s=s->parent;
}
}
}
return *this;
}
treeNode<T>* LLrotation(treeNode<T>* q){ //LL型
/*
q p
p z ➡️ x q
x y t y z
t
*/
treeNode<T> *p=q->leftchild;
q->leftchild=p->rightchild;
p->parent=q->parent;
p->rightchild=q;
q->parent=p;
if(q->leftchild)
q->leftchild->parent=q;
int lh,rh;
if(q->leftchild)
lh=q->leftchild->h;
else
lh=0;
if(q->rightchild)
rh=q->rightchild->h;
else
rh=0;
q->h=(lh>rh)? lh+1:rh+1;
if(p->leftchild)
lh=p->leftchild->h;
else
lh=0;
if(p->rightchild)
rh=p->rightchild->h;
else
rh=0;
p->h=(lh>rh)? lh+1:rh+1;
return p;
}
treeNode<T>* LRrotation(treeNode<T>* q){ //LR型,相当于先RR,再LL
/*
q q y
z w ➡️ y w ➡️ z q
x y z t x t w
t x
*/
q->leftchild=RRrotation(q->leftchild);
return LLrotation(q);
}
treeNode<T>* RLrotation(treeNode<T>* q){ //RL型,相当于先LL,再RR
/*
q q x
w z ➡️ w x ➡️ q z
x y t z w t y
t y
*/
q->rightchild=LLrotation(q->rightchild);
return RRrotation(q);
}
treeNode<T>* RRrotation(treeNode<T>* q){ //RR型
/*
q p
z p ➡️ q y
x y z x t
t
*/
treeNode<T> *p=q->rightchild;
q->rightchild=p->leftchild;
p->parent=q->parent;
p->leftchild=q;
q->parent=p;
int lh,rh;
if(q->leftchild)
lh=q->leftchild->h;
else
lh=0;
if(q->rightchild)
rh=q->rightchild->h;
else
rh=0;
q->h=(lh>rh)? lh+1:rh+1;
if(p->leftchild)
lh=p->leftchild->h;
else
lh=0;
if(p->rightchild)
rh=p->rightchild->h;
else
rh=0;
p->h=(lh>rh)? lh+1:rh+1;
return p;
}
treeNode<T>* getRoot(){ //返回根节点
return root;
}
treeNode<T>* findNear(T& t){ //寻找离根节点最近的节点,并赋值给t
treeNode<T> *lmax=root->leftchild; //左子树中最大的
treeNode<T> *rmin=root->rightchild; //右子树中最小的
while(lmax->rightchild)
lmax=lmax->rightchild;
while(rmin->leftchild)
rmin=rmin->leftchild;
if((root->data-lmax->data)<=(rmin->data-root->data)){
t=lmax->data;
return lmax;
}
else{
t=rmin->data;
return rmin;
}
}
private:
treeNode<T> *root;
};
int main(){
AVLtree<int> avl;
int t;
cout<<"Please input data for AVL tree!"<<endl;
for(int i=0;i<10;i++){
cin>>t;
avl.insert(t);
}
cout<<"Height: "<<avl.height()<<endl;
int near;
avl.findNear(near);
cout<<"The nearest tree-node of root is: "<<near<<endl;
}
作业9
红黑树动态示意图:Red/Black Tree Visualization
无重复值的红黑树描述
//50 60 65 80 5 10 62 70 23 13
//5 13 50 65 80
template<typename T>
class treeNode;
template<typename T>
class bsTree {
public:
virtual treeNode<T>* find(const T& t)=0;
virtual bsTree<T>& insert(const T& t)=0;
virtual bsTree<T>& deleted(const T& t)=0;
virtual void ascend(treeNode<T> *t)=0;
};
template<typename T>
class redBlackTree;
template<typename T>
class treeNode {
friend redBlackTree<T>; //声明友元
public:
treeNode(){
parent=leftchild=rightchild=NULL;
color=-1;
}
treeNode(const T& t){
data=t;
parent=leftchild=rightchild=NULL;
color=-1;
}
private:
T data;
int color;
treeNode<T> *parent;
treeNode<T> *leftchild;
treeNode<T> *rightchild;
};
template<typename T>
class redBlackTree: public bsTree<T> {
public:
redBlackTree(){
root=NULL;
}
treeNode<T>* find(const T& t) {
treeNode<T> *p=root,*pp=NULL; //p为应该插入的位置,pp为p的父节点
while(p){
pp=p;
if(t<p->data) //如果关键值比当前节点的关键值小,进入左子树
p=p->leftchild;
else if(t>p->data) //如果关键值比当前节点的关键值大,进入右子树
p=p->rightchild;
else{ //如果关键值等于当前节点的关键值
break;
}
}
return pp;
}
bsTree<T>& insert(const T& t) {
treeNode<T> *p=find(t); //找到应该插入的位置的父节点
treeNode<T> *q=new treeNode<T>; //新建节点
q->data=t;
q->parent=p;
q->color=1;
if(!p){ //如果父节点为空,说明树为空
q->color=-1;
root=q;
return *this;
}
if(t==p->data){ //关键值存在
cout<<"Data exists!"<<endl;
return *this;
}
else if(t<p->data) //如果关键值小于父节点的值
p->leftchild=q;
else //如果关键值大于父节点的值
p->rightchild=q;
treeNode<T>*pp=p->parent;
treeNode<T>*s=new treeNode<T>;
while(p){
pp=p->parent;
if(q->color==p->color==1){
if(pp)
s=pp->parent;
else
s=NULL;
int type;
if(!s)
type=0;
else if(s->leftchild==pp)
type=1;
else
type=2;
if(pp->leftchild==p){
if(!pp->rightchild||pp->rightchild->color==-1){
if(p->leftchild==q)
pp=xybLL(pp);
else
pp=xybLR(pp);
}
else
pp=xyr(pp);
}
else{
if(!pp->leftchild||pp->leftchild->color==-1){
if(p->leftchild==q)
pp=xybRL(pp);
else
pp=xybRR(pp);
}
else
pp=xyr(pp);
}
if(type==0){
root=pp;
if(root->color==1){
root->color=-1;
/*
if(pp->leftchild==p&&p->leftchild==q)
root=xybLL(root);
else if(pp->leftchild==p&&p->rightchild==q)
root=xybLR(root);
else if(pp->rightchild==p&&p->leftchild==q)
root=xybRL(root);
else
root=xybRR(root);
*/
}
}
else if(type==1){
s->leftchild=pp;
}
else{
s->rightchild=pp;
}
if(pp->color==-1)
break;
else{
q=p->parent;
if(q)
p=q->parent;
else
p=NULL;
}
}
else
break;
}
return *this;
}
treeNode<T>* xybLL(treeNode<T>* pp){
treeNode<T>*p=pp->leftchild;
pp->leftchild=p->rightchild;
if(p->rightchild)
p->rightchild->parent=pp;
p->rightchild=pp;
p->parent=pp->parent;
pp->parent=p;
pp->color*=-1;
p->color*=-1;
return p;
}
treeNode<T>* xybLR(treeNode<T>* pp){
treeNode<T>*p=pp->leftchild;
treeNode<T>*q=p->rightchild;
q->parent=pp->parent;
pp->leftchild=q->leftchild;
q->leftchild=p;
p->rightchild=q->rightchild;
q->rightchild=pp;
p->parent=q;
pp->parent=q;
pp->color=1;
q->color=-1;
return q;
}
treeNode<T>* xybRL(treeNode<T>* pp){
treeNode<T>*p=pp->rightchild;
treeNode<T>*q=p->leftchild;
q->parent=pp->parent;
pp->rightchild=q->rightchild;
p->leftchild=q->leftchild;
q->leftchild=pp;
q->rightchild=p;
p->parent=q;
pp->parent=q;
q->color=-1;
pp->color=1;
return q;
}
treeNode<T>* xybRR(treeNode<T>* pp){
treeNode<T>*p=pp->rightchild;
pp->rightchild=p->leftchild;
if(p->leftchild)
p->leftchild->parent=pp;
p->leftchild=pp;
p->parent=pp->parent;
pp->parent=p;
pp->color*=-1;
p->color*=-1;
return p;
}
treeNode<T>* xyr(treeNode<T>* pp){
pp->color=1;
if(pp->leftchild)
pp->leftchild->color=-1;
if(pp->rightchild)
pp->rightchild->color=-1;
return pp;
}
bsTree<T>& deleted(const T& t){
treeNode<T> *p=find(t); //找到应该删除的位置
if(!p||p->data!=t){
cout<<"Delete failure!"<<endl;
return *this;
}
treeNode<T> *pp=p->parent;
int type;
if(!pp)
type=0;
else if(pp->leftchild==p)
type=1;
else
type=2;
if(p->color==1){ //红色
if(p->rightchild&&p->leftchild){ //有两个孩子
while(p->leftchild&&p->rightchild){
pp=p->parent;
if(!pp)
type=0;
else if(pp->leftchild==p)
type=1;
else
type=2;
treeNode<T> *q=p->leftchild;
treeNode<T> *c=p->rightchild;
p->leftchild=q->leftchild;
p->rightchild=q->rightchild;
if(q->leftchild)
q->leftchild->parent=p;
if(q->rightchild)
q->rightchild->parent=p;
q->rightchild=c;
c->parent=q;
q->leftchild=p;
q->parent=p->parent;
p->parent=q;
q->color=p->color;
p->color=-1;
if(type==0){
root=q;
root->parent=NULL;
}
else if(type==1)
pp->leftchild=q;
else
pp->rightchild=q;
}
}
deleteLeaf(p);
}
else if(p->color==-1){ //黑色
if(p->leftchild&&!p->rightchild){ //只有左孩子,把孩子换上来
if(type==0){
root=p->leftchild;
root->parent=NULL;
}
else if(type==2){
pp->rightchild=p->leftchild;
p->leftchild->parent=pp;
}
else {
pp->leftchild=p->leftchild;
p->leftchild->parent=pp;
}
p->leftchild->color=-1;
}
else if(p->rightchild&&!p->leftchild){ //只有右孩子,把孩子换上来
if(type==0){
root=p->rightchild;
root->parent=NULL;
}
else if(type==2){
pp->rightchild=p->rightchild;
p->rightchild->parent=pp;
}
else {
pp->leftchild=p->rightchild;
p->rightchild->parent=pp;
}
p->rightchild->color=-1;
}
else{ //有两个孩子
while(p->leftchild&&p->rightchild){
pp=p->parent;
if(!pp)
type=0;
else if(pp->leftchild==p)
type=1;
else
type=2;
treeNode<T> *q=p->leftchild;
treeNode<T> *c=p->rightchild;
p->leftchild=q->leftchild;
p->rightchild=q->rightchild;
if(q->leftchild)
q->leftchild->parent=p;
if(q->rightchild)
q->rightchild->parent=p;
q->rightchild=c;
c->parent=q;
q->leftchild=p;
q->parent=p->parent;
p->parent=q;
q->color=p->color;
if(type==0){
root=q;
root->parent=NULL;
}
else if(type==1)
pp->leftchild=q;
else
pp->rightchild=q;
}
deleteLeaf(p);
}
}
return *this;
}
bsTree<T>& deleteLeaf(treeNode<T> *t){
treeNode<T> *p=t;
treeNode<T> *pp=p->parent;
int type;
if(!pp)
type=0;
else if(pp->leftchild==p)
type=1;
else
type=2;
if(p->color==1){ //红色
if(type==2)
pp->rightchild=NULL;
else
pp->leftchild=NULL;
}
else if(p->color==-1){ //黑色
if(type==0){ //p没有孩子也没有父亲,删除后树为空
root=NULL;
}
//兄弟一定存在
else if(type==1){ //p是pp的左孩子
treeNode<T> *ppp=pp->parent;
if(!ppp)
type=0;
else if(ppp->leftchild==pp)
type=1;
else
type=2;
if(pp->rightchild->color==1){ //兄弟是红色
pp=xybRR(pp); //旋转,兄弟变黑
if(type==0)
root=pp;
else if(type==1)
ppp->leftchild=pp;
else
ppp->rightchild=pp;
deleteLeaf(p);
}
else{ //兄弟是黑色
pp->leftchild=NULL;
if(pp->rightchild->rightchild){ //右侄子存在,一定是红色
pp=xybRR(pp);
pp->rightchild->color=-1;
if(type==0)
root=pp;
else if(type==1)
ppp->leftchild=pp;
else
ppp->rightchild=pp;
}
else if(pp->rightchild->leftchild){ //左侄子存在,一定是红色
treeNode<T> *b=pp->rightchild;
b=xybLL(b);
pp->rightchild=b;
//变成了右侄子
pp=xybRR(pp);
pp->rightchild->color=-1;
if(type==0)
root=pp;
else if(type==1)
ppp->leftchild=pp;
else
ppp->rightchild=pp;
}
else if(pp->color==1){ //父节点是红色,兄弟没有孩子
pp->color=-1;
pp->rightchild->color=1;
}
else{ //父节点是黑色,兄弟是黑色,兄弟没有孩子
pp->rightchild->color=1;
}
}
}
else{ //p是pp的右孩子
treeNode<T> *ppp=pp->parent;
if(pp->leftchild->color==1) { //兄弟是红色
pp=xybLL(pp); //旋转,兄弟变黑
if(type==0)
root=pp;
else if(type==1)
ppp->leftchild=pp;
else
ppp->rightchild=pp;
deleted(p->data);
}
else{ //兄弟是黑色
pp->rightchild=NULL;
if(pp->leftchild->leftchild){ //左侄子存在,一定是红色
pp=xybLL(pp);
pp->leftchild->color=-1;
if(type==0)
root=pp;
else if(type==1)
ppp->leftchild=pp;
else
ppp->rightchild=pp;
}
else if(pp->leftchild->rightchild){ //右侄子存在,一定是红色
treeNode<T> *b=pp->leftchild;
b=xybLL(b);
pp->leftchild=b;
//变成了左侄子
pp=xybLL(pp);
pp->leftchild->color=-1;
if(type==0)
root=pp;
else if(type==1)
ppp->leftchild=pp;
else
ppp->rightchild=pp;
}
else if(pp->color==1){ //父节点是红色,兄弟没有孩子
pp->color=-1;
pp->leftchild->color=1;
}
else{ //父节点是黑色,兄弟是黑色,兄弟没有孩子
pp->leftchild->color=1;
}
}
}
}
return *this;
}
void ascend(treeNode<T> *t){
if(t->leftchild)
ascend(t->leftchild);
cout<<t->data<<" ";
if(t->rightchild)
ascend(t->rightchild);
}
treeNode<T>* getRoot(){
return root;
}
private:
treeNode<T> *root;
};
int main(){
redBlackTree<int> rbt;
int t;
cout<<"Please input 10 integers!"<<endl;
for(int i=0;i<10;i++){
cin>>t;
rbt.insert(t);
}
cout<<"Red-black tree in ascending order:"<<endl;
rbt.ascend(rbt.getRoot());
cout<<endl<<"Please input 5 integers you want to delete!"<<endl;
for(int i=0;i<5;i++){
cin>>t;
rbt.deleted(t);
}
cout<<"Red-black tree in ascending order:"<<endl;
rbt.ascend(rbt.getRoot());
cout<<endl;
return 0;
}
插入后:
删除后:
有重复值的红黑树描述
//50 60 65 80 10 62 70 70 23 13
//13 50 70 10 80
//和无重复值的红黑树描述类似,只修改了以下部分
treeNode<T>* find(const T& t) {
treeNode<T> *p=root,*pp=NULL; //p为应该插入的位置,pp为p的父节点
while(p){
pp=p;
if(t<p->data) //如果关键值比当前节点的关键值小,进入左子树
p=p->leftchild;
else //如果关键值比当前节点的关键值大,进入右子树
p=p->rightchild;
}
return pp;
}
bsTree<T>& insert(const T& t) {
treeNode<T> *p=find(t); //找到应该插入的位置的父节点
treeNode<T> *q=new treeNode<T>; //新建节点
q->data=t;
q->parent=p;
q->color=1;
if(!p){ //如果父节点为空,说明树为空
q->color=-1;
root=q;
return *this;
}
if(t<p->data) //如果关键值小于父节点的值
p->leftchild=q;
else //如果关键值大于父节点的值
p->rightchild=q;
//……
}
bsTree<T>& deleted(const T& t){
treeNode<T> *c=root,*cp=NULL; //p为应该插入的位置,pp为p的父节点
while(c){
cp=c;
if(t<c->data) //如果关键值比当前节点的关键值小,进入左子树
c=c->leftchild;
else if(t>c->data)//如果关键值比当前节点的关键值大,进入右子树
c=c->rightchild;
else
break;
}
treeNode<T> *p=cp;
if(!p||p->data!=t){
return *this;
}
else{
//……
}
deleted(t);
return *this;
}
插入后:
删除后: