采用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