基于QT Creator的红黑树

采用QT的按钮实现插入删除等控制,采用QT的文本框输出红黑树。

main.cpp

#include "mainwindow.h"
#include 
#include "rbtree.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.setWindowTitle("RedBlackTree");
    w.setObjectName("MainWindow");
    w.setStyleSheet("#MainWindow{border-image:url(C://Users//zhangyq//Desktop//bg.png);}");
    w.show();

    return a.exec();
}

mainwiindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

bool MainWindow::GetNum(int &i)   //获得键盘输入的数据
{
    bool ok;
    i = QInputDialog::getInt(this, tr("Prossing..."),
        tr("Number: "), 0, 0, 1000, 1, &ok);
    if(!ok) return false;
    return true;
}

void MainWindow::on_AddBtn_clicked()   //Add槽函数
{
    int num;

    if(!GetNum(num)) return;   //未输入数据,则直接结束

    if(t.find(num))  //如果数据已经存在,根据红黑树的定义,树中不能出现相同节点,此时向用户反馈错误信息
        QMessageBox::warning(this, tr("Warning"), tr("Number Existing!"),QMessageBox::Abort);

    t.insert(num);  //插入

    QString str;

    t.print(str);   //显示

    ui->DisplyEdit->setText(str);

}

void MainWindow::on_DelBtn_clicked()  //Deleet槽函数
{
    int num;

    if(!GetNum(num)) return;  //未输入数据,则直接结束

    if(!t.find(num))     //如果树中无此节点,向用户反馈错误信息
        QMessageBox::warning(this, tr("Warning"), tr("Can't Find!"),QMessageBox::Abort);

    t.erase(num);   //删除

    QString str;

    t.print(str);  //显示

    ui->DisplyEdit->setText(str);

}

void MainWindow::on_ResetBtn_clicked()   //Clear槽函数
{
    t.destroy(t.root());   //销毁红黑红树,释放节点
    t.root() = nullptr;
    ui->DisplyEdit->setText("");
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include 
#include 
#include 
#include 

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    bool GetNum(int &);  //获取输入数据

private slots:
    void on_AddBtn_clicked();    //Add槽函数

    void on_DelBtn_clicked();    //Delete槽函数

    void on_ResetBtn_clicked();  //Clear槽函数

private:
    RBTree t;
    Ui::MainWindow *ui;

};

#endif // MAINWINDOW_H

rbtree.cpp

#include "rbtree.h"

void RBTree::rotate_left(Node * x)   //左旋,用于重构
{
    Node * y = x->right;   //以右子节点为支点旋转

    x->right = y->left;
    if (y->left)
        y->left->parent = x;
    y->parent = x->parent;

    if (x == root())
        root() = y;
    else if (x == x->parent->left)
        x->parent->left = y;
    else
        x->parent->right = y;

    y->left = x;
    x->parent = y;
}

void RBTree::rotate_right(Node * x)   //右旋,用于重构
{
    Node * y = x->left;    //以左子节点为支点旋转

    x->left = y->right;
    if (y->right)
        y->right->parent = x;
    y->parent = x->parent;

    if (x == root())
        root() = y;
    else if (x == x->parent->right)
        x->parent->right = y;
    else
        x->parent->left = y;

    y->right = x;
    x->parent = y;
}

void RBTree::destroy(Node * node)   //树的销毁
{
    if (node == nullptr)
        return;

    destroy(node->left);  //销毁左孩子
    destroy(node->right); //销毁右孩子
    delete node;  //释放节点
}

Node *& RBTree::root()
{
    return header->left;  //head->l=root
}

void RBTree::insert_rebalance(Node * x)  //插入后重构
{
    x->color = red;

    while (x != root() && x->parent->color == red)  //父亲节点是红色时重构
    {
        if (x->parent == x->parent->parent->left)
        {
            Node * y = x->parent->parent->right;

            if (y && y->color == red)           // Case 1 叔叔节点为红色
            {
                x->parent->color = black;
                y->color = black;
                x->parent->parent->color = red;
                x = x->parent->parent;
            }
            else    //叔叔节点黑色
            {
                if (x == x->parent->right)      // Case 2当前节点为其父亲节点右孩子
                {
                    x = x->parent;
                    rotate_left(x);
                }

                x->parent->color = black;       // Case 3当前节点为其父亲节点左孩子
                x->parent->parent->color = red;
                rotate_right(x->parent->parent);
            }
        }
        else  //和上面相同,镜像操作
        {
            Node * y = x->parent->parent->left;

            if (y && y->color == red)
            {
                x->parent->color = black;
                y->color = black;
                x->parent->parent->color = red;
                x = x->parent->parent;
            }
            else
            {
                if (x == x->parent->left)
                {
                    x = x->parent;
                    rotate_right(x);
                }

                x->parent->color = black;
                x->parent->parent->color = red;
                rotate_left(x->parent->parent);
            }
        }
    }

    root()->color = black;  //最后根节点重新着色为黑色
}

void RBTree::erase_rebalance(Node * z)  //删除后重构
{
    Node * y = z;
    Node * x = nullptr;
    Node * x_parent = nullptr;

    if (y->left == nullptr)
        x = y->right;
    else if (y->right == nullptr)
        x = y->left;
    else
    {
        y = y->right;   //找右子树最小节点
        while (y->left)
            y = y->left;
        x = y->right;
    }

    if (y != z)  //y是z的祖先// the third
    {
        z->left->parent = y;
        y->left = z->left;

        if (y != z->right)
        {
            x_parent = y->parent;
            if (x)
                x->parent = y->parent;
            y->parent->left = x;
            y->right = z->right;
            z->right->parent = y;
        }
        else
            x_parent = y;

        if (root() == z)
            root() = y;
        else if (z->parent->left == z)
            z->parent->left = y;
        else
            z->parent->right = y;

        y->parent = z->parent;
        swap(y->color, z->color);
        y = z;
    }
    else
    {
        x_parent = y->parent;
        if (x)
            x->parent = y->parent;

        if (root() == z)
            root() = x;
        else if (z->parent->left == z)
            z->parent->left = x;
        else
            z->parent->right = x;
    }
    //现在,y是想要删除的节点!
    //  x是y的子节点,x必须是空节点



    // 重构的实现
    // .....
    if (y->color == black)
    {
        while (x != root() && (x == nullptr || x->color == black))
        {
            if (x == x_parent->left)
            {
                Node * w = x_parent->right;  // w can not possibly be nullptr!

                if (w->color == red)                                      // Case 1当前结点是黑色,兄弟结点是红色
                {
                    w->color = black;
                    x_parent->color = red;
                    rotate_left(x_parent);
                    w = x_parent->right;
                }

                if ((w->left == nullptr || w->left->color == black) && // Case 2当前结点是黑色,兄弟结点是黑色,两个孩子为空或是黑色
                    (w->right == nullptr || w->right->color == black))
                {
                    w->color = red;
                    x = x_parent;
                    x_parent = x_parent->parent;
                }
                else
                {
                    if (w->right == nullptr || w->right->color == black)//Case 3
                    {                                //当前结点是黑色,兄弟结点是黑色,兄弟结点的左孩子是红色,右孩子为空或是黑色
                        if (w->left)
                            w->left->color = black;
                        w->color = red;
                        rotate_right(w);
                        w = x_parent->right;
                    }

                    w->color = x_parent->color;  // Case 4
                    x_parent->color = black;     //当前结点是黑色,兄弟结点是黑色,兄弟结点的右孩子是红色,左孩子为空或红黑皆可
                    if (w->right)
                        w->right->color = black;
                    rotate_left(x_parent);
                    break;
                }
            }
            else  //和上面相同,镜像操作
            {
                Node * w = x_parent->left;

                if (w->color == red)
                {
                    w->color = black;
                    x_parent->color = red;
                    rotate_right(x_parent);
                    w = x_parent->left;
                }

                if ((w->right == nullptr || w->right->color == black) &&
                    (w->left == nullptr || w->left->color == black))
                {
                    w->color = red;
                    x = x_parent;
                    x_parent = x_parent->parent;
                }
                else
                {
                    if (w->left == nullptr || w->left->color == black)
                    {
                        if (w->right)
                            w->right->color = black;
                        w->color = red;
                        rotate_left(w);
                        w = x_parent->left;
                    }

                    w->color = x_parent->color;
                    x_parent->color = black;
                    if (w->left)
                        w->left->color = black;
                    rotate_right(x_parent);
                    break;
                }
            }
        }  // while (x != root() && (x == nullptr || x->color == black))

        if (x)
            x->color = black;
    }  // if (y->color == black)
}

RBTree::RBTree()
{
    header = new Node(0);
}

RBTree::~RBTree()
{
    destroy(root());
    delete header;
    header = nullptr;
}

Node * RBTree::insert(int key)  //插入
{
    Node * cur = root();
    Node * pre = header;

    while (cur)
    {
        pre = cur;
        if (key < cur->key)
            cur = cur->left;
        else if (key > cur->key)
            cur = cur->right;
        else
            return nullptr;
    }

    cur = new Node(key);
    cur->parent = pre;

    if (pre == header || key < pre->key)
        pre->left = cur;
    else
        pre->right = cur;

    insert_rebalance(cur);  //重构

    return cur;
}

Node * RBTree::find(int key) //查找
{
    Node * z = root();

    while (z)
    {
        if (key < z->key)
            z = z->left;
        else if (key > z->key) //和二叉排序树相同
            z = z->right;
        else
            return z;
    }

    return z;
}

void RBTree::erase(int key)  //删除
{
    Node * z = find(key);

    if (z)
    {
        erase_rebalance(z); //重构
        delete z;
    }
}

void RBTree::doprint(Node *T, int level, QString &str)
{
    if (T == nullptr) return;        //如果指针为空,返回上一层

    doprint(T->right, level + 1, str);   //打印右子树,并将层次加1
    for (int i = 0; ikey);
    str += QString(num);

    str += (T->color == red) ? "R\n\n" : "B\n\n";
    doprint(T->left, level + 1, str);    //打印左子树,并将层次加1
    str += "\n";
}

void RBTree::print(QString &str)
{

    doprint(this->root(), 1, str);

}

rbtree.h

#ifndef RBTREE_H
#define RBTREE_H

#include 
#include 
#include 

using namespace std;

enum { red = 0, black = 1 };

struct Node         //采用三叉链表表示树的节点
{
    int key;
    bool color;
    Node * parent;
    Node * left;
    Node * right;
    Node(int key = 0)
    {
        this->key = key;
        this->color = red;
        this->parent = this->left = this->right = nullptr;
    }
};

class RBTree
{
private:
    Node * header; //head->l = root
private:
    void rotate_left(Node * x);       //左旋,用于重构
    void rotate_right(Node * x);      //右旋,用于重构
    void insert_rebalance(Node * x);  //插入后重构
    void erase_rebalance(Node * z);   //删除后重构

public:
    RBTree();
    ~RBTree();
    Node * insert(int key);      //插入
    Node * find(int key);        //查找
    Node *& root();       //得到根节点
    void destroy(Node * node);   //树的销毁
    void erase(int key);         //删除
    void print(QString &);       //树形打印
    void doprint(Node *t, int level, QString &);
};

#endif // RBTREE_H

 

你可能感兴趣的:(基于QT Creator的红黑树)