Insert完善

根据规则4, 新增节点必须为红; 根据规则3, 新增节点之父节点必须为黑.

示例:

(1)插入16(红色)/55(红色), 则既不用旋转, 也不用重新染色

(2)插入82(红色), 则违反了红黑规则, 需要进行动态的调整;

红黑树所需的处理

1.单旋转

新插入的X与其父P都是红色的, 而且X还是G的外部孙子;

2.双旋转

新插入的X与其父P都是红色的, 而且X还是G的内部孙子;

3.还需要处理有两个红色孩子的节点, 将右儿子变成黑色的, 我们只允许左儿子是红色的;方法: 旋转+重新染色

insert完整实现代码:

/**注意带有 ++ 注释的为新添加的代码**/
template <typename Comparable>
void RedBlackTree<Comparable>::insert(const Comparable &x)
{current = parent = grand = great = header;nullNode->element = x;while (current->element != x){//让祖父成为曾祖父, 父亲成为祖父, 自己成为父亲//每个人都长了一辈great = grand;grand = parent;parent = current;current = (x < current->element) ? current->left: current->right;// ++//+ 处理1. 如果current节点有两个红孩子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;elseparent->right = current;// ++//+ 处理2. 如果新插入的节点破坏了红黑规则, 则还需做一次处理handleReorient( x );
}
/**自动平衡函数:[1]重新染色[2]自动旋转
*/
template <typename Comparable>
void RedBlackTree<Comparable>::handleReorient(const Comparable & item)
{// 将current节点染成红色current->color = RED;// 将current的left和right节点染成黑色current->left->color = current->right->color = BLACK;// 如果current节点的父节点也是红的 -> 单旋转 or 双旋转if( parent->color == RED ){//则将其祖父(爷爷)的颜色染成红色grand->color = RED;//然后判断新插入的节点是否是内部孙子?//如果是, 则增加一次旋转->构成双旋转//if注释: 如果该节点小于爷爷, 小于爸爸, 这两种情况不同时满足//则说明其是爷爷的内孙子if( (item < grand->element) != (item < parent->element) ){// 则依grand(祖父)节点进行旋转parent = rotate( item, grand );  // Start double rotate}// 则依great(曾祖父)节点进行旋转current = rotate( item, great );//令当前节点为黑色current->color = BLACK;}//根节点必须是黑色的header->right->color = BLACK; // Make root black
}
// 自动判断并进行旋转函数
template <typename Comparable>
typename RedBlackTree<Comparable>::Node *
RedBlackTree<Comparable>::rotate(const Comparable &item,Node *theParent )
{//位于theParent的左子树if( item < theParent->element ){//如果为真, 则说明theParent->left有左孩子,//否则, 有右孩子item < theParent->left->element ?//如果theParent左边有一棵子树, 则以theParent->left//为轴, 向右转rotateWithLeftChild( theParent->left )  :  // LL//如果theParent右边有一棵子树, 则以theParent->left//为轴, 向左转rotateWithRightChild( theParent->left ) ;  // LRreturn theParent->left;     //返回左子树}else    //位于右子树{//如果为真, 则说明theParent->right有左孩子,往右转//否则, 有右孩子, 往左转item < theParent->right->element ?rotateWithLeftChild( theParent->right ) :  // RLrotateWithRightChild( theParent->right );  // RRreturn theParent->right;    //返回右子树}
}

测试代码:

int main()
{//用NEG_INF来代表负无穷大const int NEG_INF = -999999;RedBlackTree<int> tree(NEG_INF);tree.insert(50);cout << tree.header->right->element << " " << tree.header->right->nodeColor() << endl;cout << endl;tree.insert(40);cout << tree.header->right->left->element << " " << tree.header->right->left->nodeColor() << endl << endl;//此时需要进行旋转和重新染色tree.insert(30);cout << tree.header->right->element << " " << tree.header->right->nodeColor() << endl ;cout << tree.header->right->left->element << " " << tree.header->right->left->nodeColor() << endl;cout << tree.header->right->right->element << " " << tree.header->right->right->nodeColor() << endl;return 0;
}
//由于需要用到nodeColor成员函数, 因此我们将RedBlackNode类改造如下:
template <typename Comparable>
class RedBlackNode
{friend class RedBlackTree<Comparable>;
public:RedBlackNode(const Comparable &theElement = Comparable(),RedBlackNode *theLeft = NULL,RedBlackNode *theRight = NULL,int theColor = RedBlackTree<Comparable>::BLACK): element(theElement), left(theLeft), right(theRight), color(theColor) {}public://返回当前节点的颜色, 以作测试std::string nodeColor() const{return (color == RedBlackTree<Comparable>::BLACK) ? "black" : "red";}public:Comparable element;RedBlackNode *left;RedBlackNode *right;int color;
};

红黑树其他操作

template <typename Comparable>
class RedBlackTree
{...bool isEmpty() const;void makeEmpty();Gref<Comparable> find(const Comparable & x) const;Gref<Comparable> findMin() const;Gref<Comparable> findMax() const;//递归删除所有节点void reclainMemory(Node *t) const;...
};
//析构函数完善版本
template <typename Comparable>
RedBlackTree<Comparable>::~RedBlackTree()
{if (!isEmpty())makeEmpty();delete nullNode;delete header;
}
//红黑树查找:与二叉查找树类似
template <typename Comparable>
Gref<Comparable> RedBlackTree<Comparable>::find(const Comparable &x) const
{if (isEmpty())return Gref<Comparable>();nullNode->element = x;Node *iter = header->right;while (true){if (x < iter->element)iter = iter->left;else if (x > iter->element)iter = iter->right;//如果 x == iter->elementelse if (iter != nullNode)return Gref<Comparable>(iter->element) ;elsereturn Gref<Comparable>();}
}
//查找最大值: 一路向右
template <typename Comparable>
Gref<Comparable> RedBlackTree<Comparable>::findMax() const
{if (isEmpty())return Gref<Comparable>();Node *iter = header->right;while (iter->right != nullNode){// 一直向右走iter = iter->right;}return Gref<Comparable>(iter->element);
}
//查找最小值: 一路向左
template <typename Comparable>
Gref<Comparable> RedBlackTree<Comparable>::findMin() const
{if (isEmpty())return Gref<Comparable>();Node *iter = header->right;while (iter->left != nullNode){// 一直向左走iter = iter->left;}return Gref<Comparable>(iter->element);
}
template <typename Comparable>
bool RedBlackTree<Comparable>::isEmpty() const
{if (header->right == nullNode)return true;return false;
}template <typename Comparable>
void RedBlackTree<Comparable>::makeEmpty()
{reclainMemory(header->right);header->right = nullNode;
}template <typename Comparable>
void RedBlackTree<Comparable>::reclainMemory(Node *t) const
{//t == t->left的时候, 是当t==nullNode时if (t != t->left){reclainMemory(t->left);reclainMemory(t->right);delete t;}
}

Gref设计与实现

//一个包装器: 将指针封装成为引用
template <typename Object>
class Gref
{
public:Gref(): obj(NULL) {}explicit Gref(const Object &x): obj(& x) {}const Object &get() const{if (isNull())throw NullPointerException();elsereturn * obj;}bool isNull() const{if (obj == NULL)return true;return false;}private:const Object * obj;
};

数据结构拾遗(2) --红黑树的设计与实现(中)相关推荐

  1. 数据结构拾遗(3) --红黑树的设计与实现(下)

    完整源代码: http://download.csdn.net/detail/hanqing280441589/8450041 红黑节点设计与实现 template <typename Comp ...

  2. 数据结构拾遗(1) --红黑树的设计与实现(上)

    红黑树是一种自平衡的二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组(C++ STL 中的map/set).它是在1972年由Rudolf Bayer发明的,他称之为" ...

  3. 数据结构 - 学习笔记 - 红黑树

    数据结构 - 学习笔记 - 红黑树 定义 简介 知识点 1. 结点属性 2. 前驱.后继 3. 旋转 查找 插入 父结点为黑色 父结点为红色 1. 有4种情形只需要变色(对应234树4结点) 1.1. ...

  4. 数据结构之「红黑树」

    红黑树 红黑树(Red–black tree)是一种自平衡二叉查找树.红黑树是每个节点都带有颜色属性的二叉查找树,颜色为红色或黑色. 红黑树的特性: 1.节点要么是红色要么就是黑色,不能没有颜色. 2 ...

  5. 数据结构与算法 / 红黑树

    一.定义 根节点是黑色的. 叶子节点是空的且是黑色的. 任何相邻的节点不能都为红色. 任意节点到其每个叶子节点的路径上,黑色的节点的数量相同. 二.性质 红黑树解决了 AVL 树增.删时耗时过大的问题 ...

  6. 高级数据结构与算法 | 红黑树(Red-Black Tree)

    文章目录 红黑树 红黑树的概念 红黑树的性质 红黑树与AVL树 红黑树的实现 红黑树的节点 红黑树的插入 红黑树的查找 红黑树的验证 完整代码 红黑树 红黑树的概念 红黑树,是一种二叉搜索树,但在每个 ...

  7. 父子结构查询_Java面试准备(5)之数据结构与算法——红黑树

    欢迎点赞评论+关注~~~~~~~ 如上图,二叉查找树极端情况下可能会变成一个单链表,这种查询时间复杂度就变成O(n)了,红黑树在二叉查找树的基础上进行了自平衡. 1.原理分析 如上图,红黑树具有以下特 ...

  8. MySQL索引数据结构二叉树、红黑树、B-Tree、B+Tree、Hash

    索引:帮助MySQL高效获取数据的有序的数据结构. 假设我们有一张表table,包含Clo1和Clo2两个字段 内存地址 Clo1 Clo2 0x07 1 36 0x5A 2 20 0x7A 3 80 ...

  9. 红黑树——课程设计(自顶向下JAVA版)

    红黑树(自顶向下) 前言 课程设计,仅供参考. 实现插入及调整和删除及调整. 具体实现流程讲解可参考下面的链接文章. 说明:提供文章的学姐与我的课程设计算法相同. 答辩幻灯片不再提供. 红黑树(自顶向 ...

最新文章

  1. ajax实现给JavaScript中全局变量赋值(转)
  2. WebSocket 原理
  3. php的封装继承多态,PHP面向对象深入理解之二(封装、继承、多态、克隆)
  4. 常见模块设计--数据字典
  5. Spring Boot——基于OkHTTP的GitHub第三方登录DEMO
  6. ElasticSearch常用命令记录
  7. java图片裁剪并保存_java裁剪图片并保存的示例分享
  8. c primer英文版第5版_2019足坛10大巨星:梅西第2范戴克第3,C罗第5
  9. 信息安全工程师笔记-综合知识冲刺(二)
  10. 面对数据缺失,如何选择合适的机器学习模型?
  11. 那英、那狗、那年、那事
  12. 使用小乌龟快速上手git
  13. X-Cache和X-Pad
  14. pyodbc mysql_pyodbc and mySQL
  15. 【渝粤题库】陕西师范大学151113 财经法规与职业道德
  16. XCel 项目总结 - Electron 与 Vue 的性能优化
  17. 怎么录制屏幕视频?3个简单实用方法分享
  18. Chrome 浏览器如何截取整个页面
  19. 嵌入式学习(四)——串口
  20. SP4354 TWINSNOW - Snowflakes

热门文章

  1. (王道408考研操作系统)第二章进程管理-第四节2:死锁处理策略之避免死锁(银行家算法)
  2. 面试题3:二维数组中的查找
  3. 栈溢出笔记1.10 基于SEH的栈溢出
  4. Linux中基于eBPF的恶意利用与检测机制(rootkit、驱动)
  5. JS 全局变量、局部变量(与其他语言不太一样)
  6. golang map使用总结
  7. mysql:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
  8. SQLAlchemy ORM教程之一:Create
  9. 数据结构之树状数组(候补)
  10. 面面俱到的Java接口自动化测试实战