开始造轮子-红黑树的实现
来源:互联网 发布:公务员网络培训系统 编辑:程序博客网 时间:2024/05/19 13:18
概念
红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结
点的颜色,可以是red或者black,通过对任何一条从根节点到叶子结点上
的简单路径来约束,红黑树保证最长路径不超过最短路径的两倍,因而近视
平衡。
性质
- 每个结点不是红色就是黑色
- 根节点是黑色的
- 如果一个根节点是红色的,则它的两个叶子结点是黑色的(没有两个连续
的红色结点) - 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相
同数目的黑色结
#include<stdio.h>//实现红黑树的插入、检测功能enum COLOR{ RED, BLACK,};template<class K, class V>struct RBTreeNode{ RBTreeNode(K key, V val) :_pLeft(NULL) , _pRight(NULL) , _pParent(NULL) , _key(key) , _val(val) , _col(RED) { } RBTreeNode<K, V>* _pLeft; RBTreeNode<K, V>* _pRight; RBTreeNode<K, V>* _pParent; K _key; V _val; COLOR _col;};template<class K, class V>class RBTree{public: typedef RBTreeNode<K, V> Node; RBTree() :_pRoot(NULL) { } RBTree(K key, V val) { //疑问1:问什么要调用拷贝函数 _pRoot = new Node(key, val); _pRoot->_col = BLACK; } //拷贝构造 RBTree(const RBTree<K, V>& tree) { _Copy(tree._pRoot, _pRoot); } //赋值的三种写法:普通版 交换版 利用临时变量,函数结束自动销毁 ////赋值第二种写法 //RBTree<K, V>& opeartor = (const RBTree<K, V>& tree)//返回引用 //{ // if (this != &tree)//为什么要判断:1.避免无效拷贝 // { // RBTree<K, V> tmp(tree); // swap(_root,tree->_root); // } // return *this; //} //赋值第三种写法 RBTree<K, V>& opeartor = (const RBTree<K, V> tree)//返回引用 { if (this != &tree)//为什么要判断:1.避免无效拷贝 { swap(_root, tree->_root); } return *this; } bool Find(const K &key) { Node*cur = _pRoot; while (cur) { if (cur->_key == key) { return true; } else if (cur->_key < key) { cur = cur->_pRight; } else { cur = cur->_pLeft; } } return false; } //红黑树的插入操作 bool Insert(const K&key, const V &val) { if (_pRoot == NULL) { _pRoot = new Node(key, val); _pRoot->_col = BLACK; return true; } //先找到对应位置 Node* cur = _pRoot; Node*parent = NULL; while (cur) { if (cur->_key == key) { return false; } else if (cur->_key < key) { parent = cur; cur = cur->_pRight; } else { parent = cur; cur = cur->_pLeft; } } cur = new Node(key, val); if (parent->_key < key) { parent->_pRight = cur; } else { parent->_pLeft = cur; } cur->_pParent = parent; //根据情况进行调整树 //思路:最重要的的四个节点:cur parent g u //分情况进行解决 //【情况一】cur为红,p为红,g为黑,u存在且为红 //则将p, u改为黑,g改为红,然后把g当成cur,继续向上调整。 while (cur != _pRoot&&parent->_color == RED) { Node* grand = parent->_pParent; if (parent == grand->_pLeft) { Node* uncle = grand->_pRight; if (uncle&&uncle->_col == RED)//叔叔结点颜色是红色 { grand->_col = RED; parent->_col = BLACK; uncle->_col = BLACK; cur = grand; parent = parent->_pParent;//红色结点上移,需要继续判断 } else //叔叔结点不存在或者为黑色节点 { if (cur == parent->_pRight) { Rotate(parent);//先对parent进行左旋 parent = cur; } RotateR(grand);//对祖父节点进行右旋 parent->_col = BLACK; grand->_col = RED; break; } } else { //如果cur是parent的左孩子,则需要进行先右旋将其变为左左的情况 if (cur == parent->_pLeft) { RotateR(parent); parent = cur; } RotateL(grand); parent->_col = BLACK; grand->_col = RED; break; } } _pRoot->_col = BLACK; return true; } bool IsBalance() { if (_pRoot == NULL) { return true; } if (_pRoot->_col == RED) { return false; } int count = 0; Node* cur = _pRoot; while (cur) { if (cur->_col == BLACK) { count++; } cur = cur->_pLeft; } int num = 0; return IsBalance(_pRoot, num, count); } ~RBTree() { _Detroy(_pRoot); }private: void _Copy(Node* root, Node* & newroot) { if (root == NULL) { return; } Node*cur = new Node(root->_key, root->_val); cur->_col = root->_col; newroot = cur; cur->_pParent = newroot->_pParent; _Copy(root->_pLeft, cur->_pLeft); _Copy(root->_pRight, cur->_pRight); } bool IsBalance(Node* root, int num, int&count) { if (root == NULL) { return num == count; } if (root->_col == RED&&root->_pParent->_col == RED) { return false; } if (root->_col == BLACK) { num++; } return _IsBalance(root->_pLeft, num, count) && _IsBalance(root->_pRight, num, count); } //左旋 void RotateL(Node* parent) { Node* ppNode = parent->_pParent; Node* subR = parent->_pRight; parent->_pRight = subR->_pLeft; if (subR->_pLeft) { subR->_pLeft->_pParent = parent; } if (ppNode == NULL) { _pRoot = subR; _pRoot->_pParent = NULL; } else { if (ppNode->_pLeft == parent) { ppNode->_pLeft = subR; } else { ppNode->_pRight = subR; } subR->_pParent = ppNode; } } //右旋 void RotateR(Node* parent) { Node* ppNode = parent->_pParent; Node* subL = parent->_pLeft; parent->_pLeft = subL->_pRight; if (subL->_pRight) { subL->_pRight->_pParent = parent; } subL->._pRight = parent; parent->_pParent = subL; if (ppNode == NULL) { _pRoot = subL; _pRoot->_pParent = NULL; } else { if (ppNode->_pLeft == parent) { ppNode->_pLeft = subL; } else { ppNode->_pRight = subL; } subL->_pParent = ppNode; } } //RBtree的销毁 后序销毁 void _Destroy(Node*& root) { if (root) { _Destroy(root->_pLeft); _Destroy(root->_pRight); //销毁结点 delete root; root = NULL; } }private: Node* _pRoot;};
阅读全文
0 0
- 开始造轮子-红黑树的实现
- 新的一年从造轮子开始
- 开始造轮子
- 经典造轮子-String类的实现
- 重复造轮子--IOC容器的AOP简单实现
- 我要造轮子之基于JDK的AOP实现
- 自己造轮子系列(一)------数据库连接池的实现
- 重复造轮子-C语言风格string库函数的实现
- 不要重复造轮子,但必须知道轮子怎么造的 -----listview实现下拉刷新滚动加载
- 记录造轮子的点点滴滴
- 重复造轮子的目的
- 浅谈源码--“造轮子”与“拆轮子”之间的关系
- 下次造轮子前先看看现有的轮子吧
- 重造轮子-栈实现队列
- 造轮子:补码实现与若干分析
- 关于轮子跟造轮子。
- 一个对JAVA不熟悉导致实现造轮子的悲惨故事
- qml+QZXing实现实时QRCode识别和给重复造轮子的一些建议
- MySQL笔记
- mybatis
- Java 简单工厂模式
- SDUT 1122 判断素数(循环结构)
- JDBC 封装工具类
- 开始造轮子-红黑树的实现
- 9、Mybatis拦截器的源码分析
- 动态加载fragment和实现fragment 之间的通信
- Linux定时任务之crond/crontab
- String、StringBuffer和StringBuilder的区别
- C语言指针超简单概括
- Maven入门
- react listview篇-1
- eGTouchD异常导致CPU占用率升高