完善Insert函数,让它支持自动平衡
新插入的节点一定是红色的
当新插入的节点是外部孙子节点使,进行一次单旋转
当新插入的节点是内部孙子节点,进行一次双旋转
通用的旋转函数
Except.h异常类
#pragma once
#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) {}
};
class NullPointerException : public DSException {
public:
NullPointerException(const string &msg = ""):DSException(msg) {}
};
Wrapper.h自定义引用类型类
#pragma once
#include "Except.h"
template <class Object>
class Cref {
public:
Cref():obj(NULL) {}
explicit Cref( Object &x) : obj(&x) {}
Object &get() const {
if(isNull()) {
throw NullPointerException();
} else {
return *obj;
}
}
bool isNull() const {
return obj == NULL;
}
private:
Object *obj;
};
RedBlackTree.h
#pragma once
#include <iostream>
#include "Except.h"
#include "Wrapper.h"
/*
*红黑树规则:
*1.每一个节点不是红色就是黑色
*2.根总是黑色的
*3.如果节点是红色,则他的子节点必须是黑色的
*4.从根到叶节点的每条路径,必须包含相同数目的黑色节点
*/
template <class Comparable>
class RedBlackTree;
template <class Comparable>
class RedBlackNode;
template <class Comparable>
class RedBlackTree {
public:
enum {
RED,BLACK
};
RedBlackTree(const Comparable &negInf);
~RedBlackTree();
void insert(const Comparable &x);
Cref<Comparable> find(const Comparable &x);
Cref<Comparable> findMin() const;
Cref<Comparable> findMax() const;
bool isEmpty() const;
void makeEmpty();
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* &k1) const;
void handleReorient(const Comparable &item);
RedBlackNode<Comparable> *rotate(const Comparable &item,Node *theParent) const;
void reclaimMemory(Node* t) const;
};
template <class Comparable>
class RedBlackNode {
//private: 为了测试,临时改为共有属性
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->left->color == RED && current->right->color == RED) {
handleReorient(x);
}
}
if(current != nullNode) {
throw DuplicateItemException();
}
current = new Node(x,nullNode,nullNode);
if(x < parent->element) {
parent->left = current;
} else {
parent->right = current;
}
handleReorient(x);
}
//带着左孩子向右移动
template <class Comparable>
void RedBlackTree<Comparable>::rotateWithLeftChild(Node* &k2) const {
Node *k1 = k2->left;
//横向移动
k2->left = k1->right;
//k2下降
k1->right = k2;
//k1上升成为根
k2 = k1;
}
//带着右孩子向左移动
template <class Comparable>
void RedBlackTree<Comparable>::rotateWithRightChild(Node* &k1) const {
Node *k2 = k1->right;
//横向移动
k1->right = k2->left;
//k1下降
k2->left = k1;
//k2上升成为根
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* &k1) const {
rotateWithLeftChild(k1->right);
rotateWithRightChild(k1);
}
template <class Comparable>
void RedBlackTree<Comparable>::handleReorient(const Comparable &item) {
//变色
//当发现有个节点有两个红色节点的时候,把自身变红,把两个节点变黑
current->color = RED;
current->left->color = BLACK;
current->right->color = BLACK;
//父节点是红色
if(parent->color == RED) {
//将爷爷变为红色
grand->color = RED;
//判断是内部孙子还是外部孙子
/*
*如果item小于爷爷 且 item小于爸爸 则是左外部孙子
*如果item大于爷爷 且 item大于爸爸 则是右外部孙子
*外部孙子做单旋转
*如果两个条件不同时满足则是内部孙子
*内部孙子做爽旋转
*/
if(item < grand->element != item < parent->element) {
//内部孙子加多一次旋转
parent = rotate(item,grand);
}
current = rotate(item,great);
current->color = BLACK;
}
header->right->color = BLACK;
}
//通用旋转函数
/*
*theParent是item的父节点,item为被旋转的节点
*旋转可能性:
*左子树像向转,左子树向右转
*右子树像向转,右子树向右转
*/
template <class Comparable>
RedBlackNode<Comparable> * RedBlackTree<Comparable>::rotate(const Comparable &item,Node *theParent) const {
//比父节点小则在左边,为左子树
if(item < theParent->element) {
item < theParent->left->element ?
//左子树的节点有左孩子,则往右转
rotateWithLeftChild(theParent->left) :
//左子树的节点有右孩子,则往左转
rotateWithRightChild(theParent->left);
return theParent->left;
} else {//比父节点小大则在右边,为右子树
item < theParent->right->element ?
//右子树的节点有左孩子,则往右转
rotateWithLeftChild(theParent->right) :
//右子树的节点有右孩子,则往左转
rotateWithRightChild(theParent->right);
return theParent->right;
}
}
template <class Comparable>
Cref<Comparable> RedBlackTree<Comparable>::find(const Comparable &x) {
nullNode->element = x;
Node *curr = header->right;
for(;;) {
if(x < curr->element) {
curr = curr->left;
} else if(x > curr->element) {
curr = curr->right;
} else if(curr != nullNode) {
return Cref<Comparable>(curr->element);
} else {
return Cref<Comparable>();
}
}
}
template <class Comparable>
Cref<Comparable> RedBlackTree<Comparable>::findMin() const {
if(isEmpty()) {
return Cref<Comparable>();
}
Node *itr = header->right;
while(itr->left != nullNode) {
itr = itr->left;
}
return Cref<Comparable>(itr->element);
}
template <class Comparable>
Cref<Comparable> RedBlackTree<Comparable>::findMax() const {
if(isEmpty()) {
return Cref<Comparable>();
}
Node *itr = header->right;
while(itr->left != nullNode) {
itr = itr->right;
}
return Cref<Comparable>(itr->element);
}
template <class Comparable>
bool RedBlackTree<Comparable>::isEmpty() const {
return header->right == nullNode;
}
template <class Comparable>
void RedBlackTree<Comparable>::makeEmpty() {
reclaimMemory(header->right);
header->right = nullNode;
}
template <class Comparable>
void RedBlackTree<Comparable>::reclaimMemory(Node* t) const {
if(t != t->left) {
reclaimMemory(t->left);
reclaimMemory(t->right);
delete t;
}
}
main.h
#include <iostream>
#include "RedBlackTree.h"
using namespace std;
int main()
{
const int NEG_INF = -99999;
RedBlackTree<int> t(NEG_INF);
t.insert(50);
t.insert(40);
cout << "根是:" << t.header->right->element << endl;
t.insert(30);
cout << "动态平衡后根是:" << t.header->right->element << endl;
if(!t.isEmpty())
cout << "红黑树不是空的" << endl;
t.makeEmpty();
if(t.isEmpty())
cout << "红黑树为空" << endl;
t.insert(200);
t.insert(100);
t.insert(90);
t.insert(50);
t.insert(80);
t.insert(70);
t.insert(60);
cout << "根是:" << t.header->right->element << endl;
if(t.findMin().get() == 50)
cout << "找到最小值" << endl;
cout << t.header->right->left->element << endl;
cout << t.header->right->left->left->element << endl;
cout << t.header->right->left->left->right->element << endl;
return 0;
}