红黑树 (C++迭代)

RBTree源码实现

/*

 * BinarySearchTree.h

 *  添加元素时需自己做判断元素是否合法

 *  Created on: 2020年1月29日

 *      Author: LuYonglei

 */

 

#ifndef SRC_BINARYSEARCHTREE_H_

#define SRC_BINARYSEARCHTREE_H_

#include <queue>

#include <stack>

 

const bool RED = false;

const bool BLACK = true;

 

template<typename Element>

class BinarySearchTree {

public:

 

BinarySearchTree(int (*cmp)(Element e1, Element e2)); //比较函数指针

 

virtual ~BinarySearchTree();

 

int size(); //元素的数量

 

bool isEmpty(); //是否为空

 

void clear() {

//清空所有元素

NODE *node = root_;

root_ = nullptr;

using namespace std;

queue<NODE*> q;

q.push(node);

while (!q.empty()) {

NODE *tmp = q.front();

if (tmp->left != nullptr)

q.push(tmp->left);

if (tmp->right != nullptr)

q.push(tmp->right);

delete tmp;

q.pop();

}

}

 

void add(Element e) {

//添加元素

add(e, cmp_);

}

 

void remove(Element e) {

//删除元素

remove(Node(e, cmp_));

}

 

bool contains(Element e) {

//是否包含某元素

return Node(e, cmp_) != nullptr;

}

 

void preorderTraversal(bool (*visitor)(Element e)) {

//前序遍历

preorderTraversal(root_, visitor);

}

 

void inorderTraversal(bool (*visitor)(Element e)) {

//中序遍历

inorderTraversal(root_, visitor);

}

 

void postorderTraversal(bool (*visitor)(Element e)) {

//后序遍历

postorderTraversal(root_, visitor);

}

 

void levelOrderTraversal(bool (*visitor)(Element e)) {

//层序遍历,迭代实现

levelOrderTraversal(root_, visitor);

}

 

int height() {

//树的高度

return height(root_);

}

 

bool isComplete() {

//判断是否是完全二叉树

return isComplete(root_);

}

 

private:

 

int size_;

 

typedef struct _Node {

Element e;

_Node *parent;

_Node *left;

_Node *right;

bool color_;

_Node(Element e_, _Node *parent_) :

e(e_), parent(parent_), left(nullptr), right(nullptr), color_(

RED) {

//节点构造函数

}

 

inline bool isLeaf() {

return (left == nullptr && right == nullptr);

}

 

inline bool hasTwoChildren() {

return (left != nullptr && right != nullptr);

}

 

inline bool isLeftChild() {

//判断节点是否是父亲节点的左子结点

return parent != nullptr && parent->left == this;

}

 

inline bool isRightChild() {

//判断节点是否是父亲节点的右子结点

return parent != nullptr && parent->right == this;

}

 

inline _Node* sibling() {

//返回兄弟节点

if (this->parent != nullptr) {

if (this->isLeftChild())

return this->parent->right;

else

return this->parent->left;

}

return nullptr;

}

 

} NODE;

 

NODE *root_;

 

int (*cmp_)(Element e1, Element e2); //为实现树的排序的个性化配置,私有成员保存一个比较函数指针

 

NODE* Node(Element e, int (*cmp_)(Element e1, Element e2)) {

//返回e元素所在的节点

NODE *node = root_;

while (node != nullptr) {

int cmp = cmp_(e, node->e);

if (cmp == 0) //找到了元素

return node;

if (cmp > 0) { //待寻找元素大于节点存储的元素

node = node->right;

} else { //待寻找元素小于节点存储的元素

node = node->left;

}

}

return nullptr;

}

 

NODE* predecessor(NODE *node) {

//返回node的前驱节点

if (node == nullptr)

return nullptr;

//前驱节点在左子树

NODE *tmp = node->left;

if (tmp != nullptr) {

while (tmp->right != nullptr)

tmp = tmp->right;

return tmp;

}

//从父节点,祖父节点中寻找前驱节点

while (node->parent != nullptr && node == node->parent->left) {

node = node->parent;

}

return node->parent;

}

 

NODE* successor(NODE *node) {

//返回node的后继节点

if (node == nullptr)

return nullptr;

//后继节点在右子树

NODE *tmp = node->right;

if (tmp != nullptr) {

while (tmp->left != nullptr)

tmp = tmp->left;

return tmp;

}

//从父节点,祖父节点中寻找后继节点

while (node->parent != nullptr && node == node->parent->right) {

node = node->parent;

}

return node->parent;

}

 

bool colorOf(NODE *node) {

//返回节点的颜色

return node == nullptr ? BLACK : node->color_;

}

 

bool isBlack(NODE *node) {

//node是否为黑色

return node == nullptr ? true : node->color_ == BLACK;

}

 

bool isRed(NODE *node) {

//node是否为红色

return node == nullptr ? false : node->color_ == RED;

}

 

NODE* color(NODE *node, bool color) {

//对节点染色

if (node == nullptr)

return node;

node->color_ = color;

return node;

}

 

NODE* red(NODE *node) {

//把节点染成红色

return color(node, RED);

}

 

NODE* black(NODE *node) {

//把节点染成黑色

return color(node, BLACK);

}

 

void afterRotate(NODE *gNode, NODE *pNode, NODE *child) {

//在左旋转与右旋转中统一调用

pNode->parent = gNode->parent;

if (gNode->isLeftChild())

gNode->parent->left = pNode;

else if (gNode->isRightChild())

gNode->parent->right = pNode;

else

//此时gNode->parent 为nullptr,gNode为root节点

root_ = pNode;

if (child != nullptr)

child->parent = gNode;

gNode->parent = pNode;

 

}

 

void rotateLeft(NODE *gNode) {

//对gNode进行左旋转

NODE *pNode = gNode->right;

NODE *child = pNode->left;

gNode->right = child;

pNode->left = gNode;

afterRotate(gNode, pNode, child);

 

}

 

void rotateRight(NODE *gNode) {

//对gNode进行右旋转

NODE *pNode = gNode->left;

NODE *child = pNode->right;

gNode->left = child;

pNode->right = gNode;

afterRotate(gNode, pNode, child);

 

}

 

void afterAdd(NODE *node) {

while (true) {

//添加node之后的操作

NODE *parentNode = node->parent;

//没有父节点时,新添加的节点是root_或者上溢到root_

if (parentNode == nullptr) {

black(node);

return;

}

//1.当父亲节点为黑色节点时,不做任何处理,直接返回

if (isBlack(parentNode))

return;

NODE *uncleNode = parentNode->sibling();

NODE *grandNode = red(parentNode->parent);

if (isRed(uncleNode)) {

//2.uncle节点是红色,(上溢,只需要染色)

black(parentNode);

black(uncleNode);

//祖父节点当作是新添加的节点

node = grandNode;

continue;

}

//3.uncle节点是黑色或者uncle节点为null

if (parentNode->isLeftChild()) {

if (node->isLeftChild()) {

//LL

black(parentNode);

} else {

//LR

black(node);

rotateLeft(parentNode);

}

rotateRight(grandNode);

return;

} else {

if (node->isLeftChild()) {

//RL

black(node);

rotateRight(parentNode);

} else {

//RR

black(parentNode);

}

rotateLeft(grandNode);

return;

}

}

}

 

void add(Element e, int (*cmp_)(Element e1, Element e2)) {

//当树为空时,添加的节点作为树的根节点

if (root_ == nullptr) {

root_ = new NODE(e, nullptr);

size_++;

afterAdd(root_);

return;

}

//当添加的节点不是第一个节点

NODE *parent = root_;

NODE *node = root_;

int cmp = 0; //比较结果

while (node != nullptr) {

parent = node; //保存父节点

cmp = cmp_(e, node->e); //由函数指针来比较

if (cmp > 0) {

node = node->right; //添加的元素大于节点中的元素

} else if (cmp < 0) {

node = node->left; //添加的元素小于节点中的元素

} else {

node->e = e; //相等时就覆盖

return; //添加的元素等于节点中的元素,直接返回

}

}

//判断要插入父节点的哪个位置

NODE *newNode = new NODE(e, parent); //为新元素创建节点

if (cmp > 0) {

parent->right = newNode; //添加的元素大于节点中的元素

} else {

parent->left = newNode; //添加的元素小于节点中的元素

}

size_++;

afterAdd(newNode);

}

 

void afterRemove(NODE *node) {

while (true) {

//删除节点之后的操作

//node是要被释放内存的节点或是是替代的节点

//1.如果删除的是红色节点,直接删掉即可

//此处代表删除的节点为红色叶子节点

if (isRed(node)) {

//2.如果删除的节点是黑色节点,且替代的节点为红色节点

//此处代表删除的节点的度为1,且要删除的节点含有一个红色子节点

black(node);

return;

}

//3.如果删除的节点是黑色节点,且替代的节点为黑色节点(nullptr)

//此处代表要删除的是黑色叶子节点或根节点

NODE *parentNode = node->parent;

//如果删除的是根节点

if (parentNode == nullptr)

return;

 

//此时node为叶子节点

//但想获得他的兄弟节点不能调用sibling(),因为在调用afterRemove()之前,若node为parent的left就已经将parent的left置为nullptr

//若node为parent的right就已经将parent的right置为nullptr,此时再调用sibling()就会得不到准确的信息

bool left = parentNode->left == nullptr || node->isLeftChild();

NODE *siblingNode = left ? parentNode->right : parentNode->left;

if (left) {

//被删除的节点在左边,兄弟节点在右边

if (isRed(siblingNode)) {

//兄弟节点是红色,要转化成兄弟节点是黑色

black(siblingNode);

red(parentNode);

rotateLeft(parentNode);

//更换兄弟

siblingNode = parentNode->right;

}

//以下代码处理兄弟节点是黑色(兄弟节点必然为黑色)

if (isBlack(siblingNode->left) && isBlack(siblingNode->right)) {

//兄弟节点没有红色子节点,父节点要向下和兄弟节点合并

bool parentIsBlack = isBlack(parentNode);

black(parentNode);

red(siblingNode);

if (parentIsBlack) {

//如果父亲节点是黑色,会产生下溢

node = parentNode;

continue;

}

return;

} else {

//兄弟节点至少有一个红色子节点,向兄弟节点借元素

//兄弟节点的右边是黑色的,兄弟要先旋转

if (isBlack(siblingNode->right)) {

rotateRight(siblingNode);

siblingNode = parentNode->right;

}

color(siblingNode, colorOf(parentNode));

black(parentNode);

black(siblingNode->right);

rotateLeft(parentNode);

return;

}

} else {

//被删除的节点在右边,兄弟节点在左边

if (isRed(siblingNode)) {

//兄弟节点是红色,要转化成兄弟节点是黑色

black(siblingNode);

red(parentNode);

rotateRight(parentNode);

//更换兄弟

siblingNode = parentNode->left;

}

//以下代码处理兄弟节点是黑色(兄弟节点必然为黑色)

if (isBlack(siblingNode->left) && isBlack(siblingNode->right)) {

//兄弟节点没有红色子节点,父节点要向下和兄弟节点合并

bool parentIsBlack = isBlack(parentNode);

black(parentNode);

red(siblingNode);

if (parentIsBlack) {

//如果父亲节点是黑色,会产生下溢

node = parentNode;

continue;

}

return;

} else {

//兄弟节点至少有一个红色子节点,向兄弟节点借元素

//兄弟节点的左边是黑色的,兄弟要先旋转

if (isBlack(siblingNode->left)) {

rotateLeft(siblingNode);

siblingNode = parentNode->left;

}

color(siblingNode, colorOf(parentNode));

black(parentNode);

black(siblingNode->left);

rotateRight(parentNode);

return;

}

}

}

}

 

void remove(NODE *node_) {

//删除某一节点

if (node_ == nullptr)

return;

size_--;

//优先删除度为2的节点

if (node_->hasTwoChildren()) {

NODE *pre = successor(node_); //找到node_的后继节点

node_->e = pre->e; //用后继节点的值覆盖度为2的节点的值

//删除后继节点(后继节点的度只能为1或0)

node_ = pre;

}

//此时node_的度必然为0或1

NODE *replacement = node_->left != nullptr ? node_->left : node_->right;

if (replacement != nullptr) { //node_的度为1

replacement->parent = node_->parent;

if (node_->parent == nullptr) //度为1的根节点

root_ = replacement;

else if (node_->parent->left == node_)

node_->parent->left = replacement;

else

node_->parent->right = replacement;

afterRemove(replacement);

delete node_;

} else if (node_->parent == nullptr) { //node_是叶子节点,也是根节点

root_ = nullptr;

delete node_;

} else { //node_是叶子节点,但不是根节点

if (node_->parent->left == node_)

node_->parent->left = nullptr;

else

node_->parent->right = nullptr;

afterRemove(node_);

delete node_;

}

}

 

void preorderTraversal(NODE *node, bool (*visitor)(Element e)) {

//迭代实现前序遍历

if (node == nullptr || visitor == nullptr)

return;

using namespace std;

stack<NODE*> s;

while (true) {

if (node != nullptr) {

//访问node节点

if (visitor(node->e))

return;

//右子节点入栈

if (node->right != nullptr)

s.push(node->right);

//向左走

node = node->left;

} else if (s.size() == 0) {

return;

} else {

//没有左边节点,但是栈不为空

node = s.top();

s.pop();

}

}

}

 

void inorderTraversal(NODE *node, bool (*visitor)(Element e)) {

//迭代实现中序遍历

if (node == nullptr || visitor == nullptr)

return;

using namespace std;

stack<NODE*> s;

while (true) {

if (node != nullptr) {

//向左走

s.push(node);

node = node->left;

} else if (s.size() == 0) {

return;

} else {

//node为nullptr,且栈不为空

node = s.top();

s.pop();

//访问node节点

if (visitor(node->e))

return;

//对右子节点进行中序遍历

node = node->right;

}

}

}

 

void postorderTraversal(NODE *node, bool (*visitor)(Element e)) {

//迭代实现后序遍历

if (node == nullptr || visitor == nullptr)

return;

using namespace std;

//记录上一次弹出被访问的节点

NODE *prevNode = nullptr;

stack<NODE*> s;

s.push(node);

while (s.size() != 0) {

NODE *top = s.top();

if (top->isLeaf()

|| (prevNode != nullptr && prevNode->parent == s.top())) {

//栈顶为叶子节点或者(上一次有弹出元素且弹出元素的父节点是当前栈顶元素)

prevNode = s.top();

s.pop();

//访问node节点

if (visitor(prevNode->e))

return;

} else {

if (top->right != nullptr)

s.push(top->right);

if (top->left != nullptr)

s.push(top->left);

}

}

}

 

void levelOrderTraversal(NODE *node, bool (*visitor)(Element e)) {

if (node == nullptr || visitor == nullptr)

return;

using namespace std;

queue<NODE*> q;

q.push(node);

while (!q.empty()) {

NODE *node = q.front();

if (visitor(node->e) == true)

return;

if (node->left != nullptr)

q.push(node->left);

if (node->right != nullptr)

q.push(node->right);

q.pop();

}

}

 

int height(NODE *node) {

//某一节点的高度

if (node == nullptr)

return 0;

using namespace std;

queue<NODE*> q;

q.push(node);

int height = 0;

int levelSize = 1; //每一层起始的节点个数

while (!q.empty()) {

NODE *node = q.front();

levelSize--;

if (node->left != nullptr)

q.push(node->left);

if (node->right != nullptr)

q.push(node->right);

q.pop();

if (levelSize == 0) {

height++;

levelSize = q.size();

}

}

return height;

}

 

bool isComplete(NODE *node) {

if (node == nullptr)

return false;

using namespace std;

queue<NODE*> q;

q.push(node);

bool leaf = false; //判断接下来的节点是否为叶子节点

while (!q.empty()) {

NODE *node = q.front();

if (leaf && !node->isLeaf()) //判断叶子节点

return false;

if (node->left != nullptr) {

q.push(node->left);

} else if (node->right != nullptr) { //node->left == nullptr && node->right != nullptr

return false;

}

if (node->right != nullptr) {

q.push(node->right);

} else { //node->right==nullptr

leaf = true;

}

q.pop();

}

return true;

}

 

};

 

template<typename Element>

BinarySearchTree<Element>::BinarySearchTree(int (*cmp)(Element e1, Element e2)) :

size_(0), root_(nullptr), cmp_(cmp) {

//树的构造函数

}

 

template<typename Element>

BinarySearchTree<Element>::~BinarySearchTree() {

// 析构函数

clear();

}

 

template<typename Element>

inline int BinarySearchTree<Element>::size() {

//返回元素个数

return size_;

}

 

template<typename Element>

inline bool BinarySearchTree<Element>::isEmpty() {

//判断是否为空树

return size_ == 0;

}

 

#endif /* SRC_BINARYSEARCHTREE_H_ */

 

main测试例程

/*

 * main.cpp

 *

 *  Created on: 2020年1月29日

 *      Author: LuYonglei

 */

 

#include "BinarySearchTree.h"

#include <iostream>

 

using namespace std;

 

template<typename Element>

int compare(Element e1, Element e2) {

//比较函数,相同返回0,e1<e2返回-1,e1>e2返回1

return e1 == e2 ? 0 : (e1 < e2 ? -1 : 1);

}

 

template<typename Elemnet>

bool visitor(Elemnet e) {

cout << e << " ";

return false; //若返回true,则在遍历时会退出

}

 

int main(int argc, char **argv) {

BinarySearchTree<double> a(compare);

double arr[] = { 48, 3, 63, 6, 7, 21, 41, 60, 25, 82, 44, 90, 45, 23, 16 };

for (int i = 0; i < sizeof(arr) / sizeof(double); i++)

a.add(arr[i]);

// a.inorderTraversal(visitor);

// cout << endl;

// cout << a.isComplete() << endl;

// a.remove(21);

// a.remove(44);

// a.remove(48);

// a.remove(45);

// a.remove(26);

// a.remove(3);

// a.remove(60);

// a.clear();

a.postorderTraversal(visitor);

// cout << endl;

// a.levelOrderTraversal(visitor);

// cout << endl;

// cout<<a.contains(0)<<endl;

}

 

原文链接: https://www.cnblogs.com/luyl/p/12300428.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    红黑树 (C++迭代)

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/329249

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月1日 下午5:03
下一篇 2023年3月1日 下午5:03

相关推荐