我们今天把双旋转加到红黑树里面,单旋转有的时候不能让二叉查找树平衡,所以需要调用双旋转。双旋转就是把两个单旋转放在一起形成双旋转。
在头文件中加入Except.h和RedBlackTree.h,在源文件中加入TestRedBlackTree.cpp
//Except.h
#ifndef EXCEPT_H
#define EXCEPT_H
#include<string>
using namespace std;
class DSException{
public:
DSException(const string & msg = "") :message(msg){}
virtual ~DSException(){}
virtual string toString() const{
return "Exception " + string(":") + what();
}
virtual string what() const{
return message;
}
private:
string message;
};
class DuplicateItemException :public DSException{
public:
DuplicateItemException(const string & msg = "") :DSException(msg){}
};
#endif
//RedBlackTree.h
//红黑树主要程序
#ifndef RED_BLACK_TREE_H_
#define RED_BLACK_TREE_H_
#include"Except.h"
template<class Comparable>
class RedBlackTree;
template<class Comparable>
class RedBlackNode;
template<class Comparable>
class RedBlackTree{
public:
RedBlackTree(const Comparable & negInf);//红黑树的构造函数
~RedBlackTree();
enum{RED,BLACK};
void insert(const Comparable & x);
typedef RedBlackNode<Comparable> Node;
//private:为了测试,临时变成公有的
public:
Node *header;
Node *nullNode;
Node *current;//当前节点
Node *parent;//父结点
Node *grand;//祖父节点
Node *great;//曾祖父节点
void rotateWithLeftChild(Node * & k2) const;
void rotateWithRightChild(Node * & k1) const;
void doubleRotateWithLeftChild(Node * & k3)const;
void doubleRotateWithRightChild(Node * & k4)const;
};
template<class Comparable>
class RedBlackNode{
//private:为了测试,临时变成public
public:
Comparable element;
RedBlackNode *left;
RedBlackNode *right;
int color;
RedBlackNode(const Comparable & theElement = Comparable(),
RedBlackNode *lt = NULL,
RedBlackNode *rt = NULL,
int c = RedBlackTree<Comparable>::BLACK)
:element(theElement), left(lt), right(rt), color(c){}
friend class RedBlackTree<Comparable>;
};
template<class Comparable>
RedBlackTree<Comparable>::RedBlackTree(const Comparable & negInf){
nullNode = new Node();
nullNode->left = nullNode->right = nullNode;
header = new Node(negInf);
header->left = header->right = nullNode;
}
template<class Comparable>
RedBlackTree<Comparable>::~RedBlackTree(){
delete nullNode;
delete header;
}
template<class Comparable>
void RedBlackTree<Comparable>::insert(const Comparable & x){
current = parent = grand = header;
nullNode->element = x;
while (current->element != x){
great = grand; grand = parent; parent = current;
current = x < current->element ? current->left : current->right;
}
if (current != nullNode)
throw DuplicateItemException();
current = new Node(x, nullNode, nullNode);
if (x < parent->element)
parent->left = current;
else
parent->right = current;
//自动平衡 -> 红黑树
}
template<class Comparable>
void RedBlackTree<Comparable>::rotateWithLeftChild(Node * & k2)const{
Node *k1 = k2->left;
k2->left = k1->right;//横向移动
k1->right = k2;
k2 = k1;
}
template<class Comparable>
void RedBlackTree<Comparable>::rotateWithRightChild(Node * & k1)const{
Node *k2 = k1->right;
k1->right = k2->left;
k2->left = k1;
k1 = k2;
}
template<class Comparable>//双旋转_向右旋转
void RedBlackTree<Comparable>::doubleRotateWithLeftChild(Node * & k3)const{
rotateWithRightChild(k3->left);
rotateWithLeftChild(k3);
}
template<class Comparable>//双旋转_向左旋转
void RedBlackTree<Comparable>::doubleRotateWithRightChild(Node * & k4)const{
rotateWithLeftChild(k4->right);
rotateWithRightChild(k4);
}
#endif
//TestRedBlackTree.cpp
#include<iostream>
#include"RedBlackTree.h"
using namespace std;
int main(){
cout << "测试红黑树:" << endl;
const int NEG_INF = -99999;//负的无穷大,
RedBlackTree<int> t(NEG_INF);//创建一个空树,
t.insert(12);
t.insert(16);
t.insert(8);
t.insert(10);
t.insert(4);
t.insert(14);
t.insert(2);
t.insert(6);
t.insert(5);
cout << t.header->right->left->left->right->left->element << endl;
cout << "旋转之前:" << endl;
cout << t.header->right->left->element << endl;
cout << "向右双旋转:" << endl;
t.doubleRotateWithLeftChild(t.header->right->left);
cout << t.header->right->left->element << endl;
cout << t.header->right->left->left->right->element << endl;
system("pause");
return 0;
}
总结:但旋转不能满足红黑树的需要,所以需要双旋转,使红黑树能够自动平衡二叉查找树。我们做的单旋转和双旋转都是为insert服务的,如果insert里面不能使二叉查找树旋转,那么就是普通的二叉查找树,我在下一个博客里面把旋转加到insert里面,构成真正的红黑树。