当前位置: 首页 > news >正文

网站建设与规划总结/网上永久视频会员是真的吗

网站建设与规划总结,网上永久视频会员是真的吗,无锡品牌网站建设介绍,网站建设网络推广首选公司红黑树的概念与模拟实现 红黑树的概念红黑树的性质红黑树节点的定义红黑树的迭代器红黑树的插入红黑树和AVL树的比较红黑树的模拟实现 红黑树的概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。…

红黑树的概念与模拟实现

  • 红黑树的概念
  • 红黑树的性质
  • 红黑树节点的定义
  • 红黑树的迭代器
  • 红黑树的插入
  • 红黑树和AVL树的比较
  • 红黑树的模拟实现

红黑树的概念

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。
在这里插入图片描述

红黑树的性质

1.每个结点不是红色就是黑色
2.根节点是黑色的
3.如果一个节点是红色的,则它的两个孩子结点是黑色的
4.对于每个结点,从该结点到其所有后代叶结点的简单路径上均包含相同数目的黑色结点
5.每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

红黑树节点的定义

enum Color
{RED, BLACK
};template<class T>
struct RBTreeNode
{RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;T _data;Color _color;RBTreeNode(const T& data = T(), Color color = RED):_left(nullptr),_right(nullptr),_parent(nullptr),_data(data),_color(color){}
};

红黑树的迭代器

首先我们来看下红黑树中的迭代器应该是在什么位置
在这里插入图片描述

红黑树的结构中,有一个根节点,也有一个头节点,头节点是不负责存储数据的,而根节点才是常规意义上的二叉树的根节点,而红黑树中,begin()在头节点的左子树,也就是最左侧的节点(因为红黑树也是二叉平衡树),最左侧的节点就是最小的节点,end()在头节点的位置,因为如果对end()减减时,需要让迭代器走到最后一个节点的位置,也就意味着end应该指向最后一个节点的下一个位置。

首先,不关注红黑树节点中的值,因为作为迭代器,并不会对红黑树的结构进行修改,也就不会破坏红黑树,所以可以忽略红黑树的性质,只去关注它作为一棵二叉平衡树的特点。

核心的代码就变成了如何对迭代器实现Increment和Decrement操作,也就是加加减减操作

红黑树的插入

红黑树的插入实际上是分两个步骤的: 第一步,先用插入二叉搜索树的方式进行插入: 先拿到当前树的根节点,判断当前树是否为空
1.若为空,则创建一个根节点,作为头节点的parent,根节点和头节点互为parent
2.若不为空,从根节点开始,找待插入的节点位置
3.找到插入位置后,插入节点(默认的插入颜色是红色)
4.需要检测插入节点后,红黑树的性质是否被破坏了
5.检测完毕,并且进行修改
6.修改根节点的颜色,并且修改头节点的左右指向

对于步骤4是最重要的一步,因为涉及到红黑树的性质被破坏后,如何进行修改
我们可以分几种情况来进行讨论:
注意:cur为当前节点,p为父节点, g为祖父节点,u为叔叔节点

情况1.cur为红,p为红,g为黑,u存在且为红

在这里插入图片描述

那么就需要将p和u的颜色改为黑,同时将g的颜色改为红。
1.这时候就需要看g是否是根节点了,如果是根节点,只需要将根节点修改为黑即可。
2.如果g不是根节点,那么就需要继续向上判断,如果g的双亲是黑,也不需要进行任何修改,但是如果g的双亲是红,就违反了性质3,需要继续向上修改----->相当于将g作为cur,继续向上调整

情况2.cur为红,p为红,g为黑,u不存在/u存在且为黑

对于第一种:u不存在的情况
在这里插入图片描述

可以推断出,cur一定是新插入的节点,因为如果cur不是新插入的节点,那么cur和p一定要有一个是黑色,不然就违反了性质4
对于第二种:u存在的情况
在这里插入图片描述
u一定是黑色的,cur节点原来的颜色也是黑色的,现在看到是红色是由于cur的子树在调整时将cur的颜色由黑色改为红色了。

对于这两种场景的解决方案是:
p为g的左孩子,cur为p的左孩子,则进行右单旋;
p为g的右孩子,cur为p的右孩子,则进行左单旋。

旋转完成后,p变黑,g变红。
在这里插入图片描述

在这里插入图片描述

场景3:cur为红,p为红,g为黑,u不存在/u存在且为黑 和场景2相似,区别在于场景3中cur的位置,
如果p在g的左侧,cur在p的右侧,也就是内侧。
如果p在g的右侧,cur在p的左侧,也就是内侧。

在这里插入图片描述

p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;
p为g的右孩子,cur为p的左孩子,则针对p做右单旋转
通过这样的旋转之后,情况3就变成了情况2,再对情况2进行处理

当然,上述的三种情况是指parent在祖父节点的左,还有三种情况是可能在祖父节点的右。和上述的情况刚好相反。

红黑树和AVL树的比较

红黑树和AVL树都是高效的平衡二叉树,增删改查的时间复杂度都是O( l o g 2 N log_2 N log2N),红黑树不追求绝对平衡,其只需保证最长路径不超过最短路径的2倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL树更优,而且红黑树实现比较简单,所以实际运用中红黑树更多。

红黑树的模拟实现

#pragma once#include <iostream>
using namespace std;
#include <functional>enum Color
{RED, BLACK
};template<class T>
struct RBTreeNode
{RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;T _data;Color _color;RBTreeNode(const T& data = T(), Color color = RED): _left(nullptr), _right(nullptr), _parent(nullptr), _data(data), _color(color){}
};template<class T, class Ref, class Ptr>
struct RBTreeIterator
{typedef RBTreeNode<T> Node;typedef RBTreeIterator<T, Ref, Ptr> Self;
public:RBTreeIterator(Node* pNode = nullptr): _pNode(pNode){}// 具有指针类似的操作Ref operator*(){return _pNode->_data;}Ptr operator->(){return &(operator*());}// 能够移动Self& operator++(){Increment();return *this;}Self operator++(int){Self temp(*this);Increment();return temp;}Self& operator--(){Decrement();return *this;}Self operator--(int){Self temp(*this);Decrement();return temp;}// 迭代器可以比较bool operator!=(const Self& s)const{return _pNode != s._pNode;}bool operator==(const Self& s)const{return _pNode == s._pNode;}private:void Increment(){if (_pNode->_right){_pNode = _pNode->_right;while (_pNode->_left){_pNode = _pNode->_left;}}else{Node* parent = _pNode->_parent;while (_pNode == parent->_right){_pNode = parent;parent = _pNode->_parent;}// 注意特殊情况:根没有右孩子场景if(_pNode->_right != parent)_pNode = parent;}}void Decrement(){if (_pNode->_parent->_parent == _pNode && RED == _pNode->_color){_pNode = _pNode->_right;}else if (_pNode->_left){_pNode = _pNode->_left;while (_pNode->_right){_pNode = _pNode->_right;}}else{Node* parent = _pNode->_parent;while (_pNode == parent->_left){_pNode = parent;parent = _pNode->_parent;}_pNode = parent;}}
private:Node* _pNode;
};// 假设:key唯一
template<class T, class KOFD, class Compare = less<T>>
class RBTree
{typedef RBTreeNode<T> Node;public:typedef RBTreeIterator<T, T&, T*> iterator;public:RBTree(): _size(0){_head = new Node();_head->_left = _head;_head->_right = _head;}~RBTree(){_DestroyRBTree(GetRoot());delete _head;_head = nullptr;}iterator begin(){return iterator(_head->_left);}iterator end(){return iterator(_head);}pair<iterator, bool> Insert(const T& data){// 1. 二叉搜索树// 按照二叉搜索树的规则插入新节点// 空树Node*& root = GetRoot();Node* newNode = nullptr;if (nullptr == root){newNode = root = new Node(data, BLACK);root->_parent = _head;}else{// 非空:// 找待插入节点在红黑树中的位置并保存其双亲Node* cur = root;Node* parent = _head;KOFD kofD;while (cur){parent = cur;if (_com(kofD(data), kofD(cur->_data)))cur = cur->_left;else if (_com(kofD(cur->_data), kofD(data)))cur = cur->_right;elsereturn make_pair(iterator(cur), false);}// 插入新节点newNode = cur = new Node(data);if (_com(kofD(data), kofD(parent->_data)))parent->_left = cur;elseparent->_right = cur;cur->_parent = parent;// 2. 节点添加颜色 + 性质约束平衡性// 检测新节点插入后,红黑树的性质是否造到破坏while (_head != parent && RED == parent->_color){// 违反性质三Node* grandFather = parent->_parent;if (parent == grandFather->_left){// 课件中的三个场景:Node* uncle = grandFather->_right;if (uncle && RED == uncle->_color){// 情况一:叔叔节点存在且为红parent->_color = BLACK;uncle->_color = BLACK;grandFather->_color = RED;cur = grandFather;parent = cur->_parent;}else{// 叔叔节点不存在 || 叔叔节点存在且为黑// 情况二和情况三if (cur == parent->_right){// 情况三RotateLeft(parent);std::swap(cur, parent);}// 情况二parent->_color = BLACK;grandFather->_color = RED;RotateRight(grandFather);}}else{// 课件中三个场景的反情况:Node* uncle = grandFather->_left;if (uncle && RED == uncle->_color){parent->_color = BLACK;uncle->_color = BLACK;grandFather->_color = RED;cur = grandFather;parent = cur->_parent;}else{if (cur == parent->_left){RotateRight(parent);std::swap(cur, parent);}parent->_color = BLACK;grandFather->_color = RED;RotateLeft(grandFather);}}}}root->_color = BLACK;_head->_left = MostLeft();_head->_right = MostRight();++_size;return make_pair(iterator(newNode), true);}size_t Size()const{return _size;}bool Empty()const{return 0 == _size;}void Clear(){_DestroyRBTree(GetRoot());_head->_left = _head;_head->_right = _head;_size = 0;}void Swap(RBTree<T, KOFD, Compare>& t){std::swap(_head, t._head);std::swap(_size, t._size);std::swap(_com, t._com);}void InOrder(){cout << "中序遍历: ";_InOrder(GetRoot());cout << endl;}iterator Find(const T& data){Node* cur = GetRoot();KOFD kofD;while (cur){if (_com(kofD(data), kofD(cur->_data)))cur = cur->_left;else if (_com(kofD(cur->_data), kofD(data)))cur = cur->_right;elsereturn iterator(cur);}return end();}bool IsVAlidTree(){Node* root = GetRoot();if (nullptr == root)return true;if (root->_color == RED){cout << "违反性质2:根是红色的" << endl;return false;}// 获取单条路径中黑色节点的个数size_t blackCount = 0;Node* cur = root;while (cur){if (BLACK == cur->_color)blackCount++;cur = cur->_left;}// 递归检测性质4return IsVAlidTree(root, blackCount, 0);}private:bool IsVAlidTree(Node* root, const size_t blackCount, size_t pathBlackCount){if (nullptr == root)return true;Node* parent = root->_parent;if (parent != _head && (RED == root->_color && RED == parent->_color)){cout << "违反了性质三:存在连在一起的红色节点!!!" << endl;return false;}if (BLACK == root->_color)pathBlackCount++;if (nullptr == root->_left && nullptr == root->_right){if (pathBlackCount != blackCount){cout << "违反了性质4:路径中黑色节点个数不一样!!!" << endl;return false;}}return IsVAlidTree(root->_left, blackCount, pathBlackCount) &&IsVAlidTree(root->_right, blackCount, pathBlackCount);}void RotateLeft(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;// 注意:右单支if (subRL)subRL = subRL->_parent = parent;subR->_left = parent;// 更新subR和parent的双亲Node* pparent = parent->_parent;parent->_parent = subR;subR->_parent = pparent;// 需要向上考虑pparentif (_head == pparent)GetRoot() = subR;else{if (parent == pparent->_left)pparent->_left = subR;elsepparent->_right = subR;}}void RotateRight(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;// 左单支if (subLR)subLR->_parent = parent;subL->_right = parent;// 更新suL和parent的双亲Node* pparent = parent->_parent;subL->_parent = pparent;parent->_parent = subL;// 向上考虑pparent的情况if (_head == pparent)GetRoot() = subL;else{if (parent == pparent->_left)pparent->_left = subL;elsepparent->_right = subL;}}void _DestroyRBTree(Node*& root){if (root){_DestroyRBTree(root->_left);_DestroyRBTree(root->_right);delete root;root = nullptr;}}void _InOrder(Node* root){if (root){_InOrder(root->_left);cout << root->_data << " ";_InOrder(root->_right);}}Node*& GetRoot(){return _head->_parent;}Node* MostLeft(){Node* root = GetRoot();if (nullptr == root)return _head;Node* cur = root;while (cur->_left){cur = cur->_left;}return cur;}Node* MostRight(){Node* root = GetRoot();if (nullptr == root)return _head;Node* cur = root;while (cur->_right){cur = cur->_right;}return cur;}private:Node* _head;size_t _size;Compare _com;
};
http://www.jmfq.cn/news/4864663.html

相关文章:

  • 长沙专业外贸网站建设/电商网站建设制作
  • 网站开发的结论/免费的短视频app大全
  • 郑州网站建设公司咨询/海外推广方法有哪些
  • 网站问卷调查系统怎么做/百度官网电话客服24小时
  • 安徽建设厅网站施/微信社群营销怎么做
  • 黄埔网站建设 信科网络/香水推广软文
  • 国内比较大的源码网站/百度高级搜索入口
  • 做网站需要规划哪些内容/武汉seo群
  • 网站建设 嘉兴/搜索引擎营销的成功案例
  • 南安网站建设/关键词歌词打印
  • 做btob上哪个网站好/百度标注平台怎么加入
  • 青岛网站建设服务器/营销团队
  • 做网站网页/网站推广服务报价表
  • 无锡企业网站制作策划/百度收录技术
  • 影院网站模板/汽车营销活动策划方案
  • 有那个网站可以做食品台账/企业网站建设方案
  • 房产cms系统哪个好/seo研究中心
  • 阿里云服务的官方网站/想要网站导航推广页
  • 已认证网站服务费怎么做/外链购买
  • 申请一个网站/独立站seo搜索优化
  • 现有什么网站可以做网上批发/如何做网络营销
  • 河北省社会保险网站/公司怎么做网站推广
  • 做网站注册会员加入实名认证功能/国内搜索网站排名
  • 做家居的网站/页面优化算法
  • 福州网站网站建设/爱站网
  • 东城网站建设/上海关键词优化公司哪家好
  • 做特卖的网站有哪些/bt种子搜索
  • 网站怎么做弹窗/无锡百度竞价推广
  • 春考网页制作素材/百度关键词优化公司哪家好
  • 南通做电力的公司网站/广州网络公司