数据结构与算法(C语言版)__红黑树06

本文介绍了红黑树的基本操作实现,包括查找、插入、删除等,并通过一个测试程序验证了红黑树的功能。文章详细解释了红黑树的自平衡机制及其实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天给红黑树添加几个函数,分别是:
find()查找
findMin()查找最小的
findMax()查找最大的
isEmpty()判断树是不是空的
makeEmpty()清空树
在头文件中添加Except.h、Wrapper.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){}
};

class NullPointerException: public DSException{
public:
    NullPointerException(const string & msg = "") :DSException(msg){}
};

#endif

下面是引用的返回类型。

//Wrapper.h
#ifndef WRAPPER_H_
#define WRAPPER_H_

#include "Except.h"

template<class Object>
class Cref{
public:
    Cref() :obj(NULL){}
    explicit Cref(const Object & x) :obj(&x){}

    bool isNull() const{
        return obj == NULL;
    }
    const Object & get() const{
        if (isNull()) throw NullPointerException(); else return *obj;
    }

private:
    const Object *obj;
};
#endif

下面是红黑树主要的程序,我们把红黑树写在头文件里面。

//RedBlackTree.h
//红黑树主程序,包含了红黑树主要的基本的功能
#ifndef RED_BLACK_TREE_H_
#define RED_BLACK_TREE_H_

#include"Except.h"
#include"Wrapper.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};

    Cref<Comparable> find(const Comparable & x) const;//返回一个引用类型,但是引用类型不能指着空对象,所以我们自己做一个返回类型。
    Cref<Comparable> findMin() const;
    Cref<Comparable> findMax() const;

    bool isEmpty() const;//用来判断二叉树是不是空树

    void makeEmpty();

    void insert(const Comparable & x);

    typedef RedBlackNode<Comparable> Node;
//private:为了测试,临时变成公有的
public:
    Node *header;
    Node *nullNode;

    Node *current;//当前节点
    Node *parent;//父结点
    Node *grand;//祖父节点
    Node *great;//曾祖父节点

    void reclaimMemory(Node *t)const;

    void rotateWithLeftChild(Node * & k2) const;
    void rotateWithRightChild(Node * & k1) const;

    void doubleRotateWithLeftChild(Node * & k3)const;
    void doubleRotateWithRightChild(Node * & k4)const;

    void handleReorient(const Comparable & item);

    RedBlackNode<Comparable>* rotate(const Comparable & item, Node *parent)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(){
    makeEmpty();
    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;//横向移动
    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);
}

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;
        if (item < grand->element != item < parent->element)//如果是内部孙子,有两次旋转
            parent = rotate(item, grand);
        current = rotate(item, great);
        current->color = BLACK;
    }
    header->right->color = BLACK;
}

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>
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;
    }
}

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->right != nullNode)
        itr = itr->right;

    return Cref<Comparable>(itr->element);
}

template<class Comparable>
Cref<Comparable> RedBlackTree<Comparable>::find(const Comparable & x)const{
    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>();
    }
}
#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(50);
    t.insert(40);
    t.insert(30);
    t.insert(20);
    t.insert(10);
    t.insert(5);
    t.insert(4);
    t.insert(3);
    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);
    if (t.findMin().get() == 50)cout << "找到最小数" << endl;
    if (t.findMax().get() == 200)cout << "找到最大值" << endl;

    Cref<int> r = t.find(60);
    if (r.isNull()){
        cout << "没找到!" << endl;
    }
    else{
        cout << "找到:" << r.get() << endl;
    }
    system("pause");
    return 0;
}

总结:今天把红黑树的基本功能都实现出来,代码比较长,但是绝对值得学习,以后的开发过程中也是这样写,一点一点把函数的功能加到我们的树里面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值