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

国内优秀网站赏析什么是网络营销的核心

国内优秀网站赏析,什么是网络营销的核心,wordpress 音乐 页面,东北做美甲的贷款在线播放英文网站目录 介绍----什么是红黑树 甲鱼的臀部----规定 分析思考 绘图解析代码实现 节点部分 插入部分分步解析 ●父亲在祖父的左,叔叔在祖父的右: ●父亲在祖父的右,叔叔在祖父的左: 测试部分 整体代码 介绍----什么是红黑树 红…

目录

介绍----什么是红黑树

 甲鱼的臀部----规定

分析思考

绘图解析+代码实现

节点部分

插入部分+分步解析

●父亲在祖父的左,叔叔在祖父的右:

●父亲在祖父的右,叔叔在祖父的左:

测试部分

整体代码


介绍----什么是红黑树

红黑树基于二叉搜索树,它和AVL树一样避免了二叉搜索树中极端场景单边树的情况,保证了检索的效率。红黑树允许最长路径是最短路径的二倍,相较于AVL树而言是近似于平衡的状态,但是减少了旋转的次数。

 甲鱼的臀部----规定

●每个节点都有颜色,不是红色就是黑色。

●根节点一定是黑色的。

●不能连续出现两个红色的节点。

●每条路径上的黑色节点数量相同。

●每个空节点都是黑色的。

●最多允许一条路径上的节点是另一条路径上节点的二倍。

分析思考

节点默认颜色应该选红色还是黑色,为什么?

答:插入红色可能会出现连续的红色节点,插入黑色会改变当前路径上的黑色节点数。选择默认插入节点为红色的原因是插入后的影响会小一些,当父节点是黑色时不用调整。相反的,黑色节点的插入一定会违反红黑树的规则。

满足上述特性为什么能保证最长路径不会超过最短路径的2倍?

答:这里要关注红黑树的两个特性,红色节点的孩子节点一定是黑色,每条路径的黑色节点树相同。也就说最长路径是红色节点和黑色交替,最短路径是全黑节点。这样一来,最长路径和最短路径间的差距就控制在了规定范围内。

绘图解析+代码实现

节点部分

三叉链结构分别指向左右孩子和父亲节点,数据方面存储键值对,除此之外还需要一个记录节点颜色的变量。

enum Color
{RED,BLACK
};template<class K,class V>
struct RBTreeNode
{RBTreeNode* _left;RBTreeNode* _right;RBTreeNode* _parent;pair<K, V> _kv;Color _color;RBTreeNode(pair<K, V> kv, Color color = RED):_left(nullptr),_right(nullptr),_parent(nullptr),_kv(kv),_color(color){}
};

插入部分+分步解析

红黑树是二叉搜索树,插入节点的规则和二叉搜索的特点一样:

   typedef RBTreeNode<K,V> Node;bool inster(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);_root->_color = BLACK;return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else{return false;}}//插入节点的位置cur = new Node(kv);cur->_color = RED;if (parent->_kv.first > kv.first){parent->_left = cur;cur->_parent = parent;}else{parent->_right = cur;cur->_parent = parent;}//节点插入后,需要检查红黑树的特性有没有被破坏掉//......}

上述我们谈论过新节点的颜色默认为红色的原因,那么接下来的插入如果新节点插入后其父节点的颜色是黑色,那么直接插入即可。如果其父节点的颜色为红色,那么就出现了两个红色节点出现的情况,此时就需要进行调整:

 

关注:红黑树的处理方法重点关注这样的几个节点:cur(新增节点)、parent(父亲节点)、uncle(叔叔节点)、grandfather(祖父节点)。

当节点的插入违反了红黑树“龟腚”时,对应不同的情况分别处理:

●父亲在祖父的左,叔叔在祖父的右:

情况1:cur为红,parent红色,叔叔节点存在且是红色,祖父是黑色;

 

如上图所示,情况1的处理方法就是将父亲和叔叔的节点变为黑色,祖父的节点变为红色。对于祖父为什么要变红是基于这样的考虑,我们当前的处理很可能只是在子树当中,如果祖父节点保持黑色不变,对于子树这两条路径而言,增加了黑色节点,这样一来就“拆东墙补了西墙”,又违反了另一条规则。如果祖父节点是根节点,改为红色当然是不合理的,我们在最后做下强制处理即可。

注意:这种情况可能是局部的处理,当祖父节点变红且不是根节点时,可能会破坏规则,所以针对情况1需要继续向上查找,也就是将祖父节点看成新增节点,祖父的父亲看做新增节点的父节点,继续向上更新检查树结构。

                if (uncle && uncle->_color == RED){//情况1,叔叔节点存在,且是红色的parent->_color = uncle->_color = BLACK;grandfater->_color = RED;//更新cur和parent的位置cur = grandfater;parent = cur->_parent;}

情况2:cur为红(插入或者调整后和父亲祖父为一条直线),parent红色,叔叔不存在或者叔叔是黑色,祖父是红色。

当叔叔不存在时:这种情况较好分析,新节点插入后左边高,左边高度超过右边的2倍,进行一次右单旋,祖父变成红色,父亲变为黑色,这颗树调整完毕,不管它是不是子树都不会向上影响。

叔叔存在且为黑色,观察下图,每条路径上的黑色节点数量不相等,所以cur的位置应该是从黑色调整为的红色。

注意:这里不要受图示的影响,感觉uncle路径上的黑节点好像是多一个。调整前后的每条路径数量都是相等的,想象小三角中有着不同的结构就可以了。

叔叔的存在与否只是分析的过程不同,它们的代码处理方式是一样的: 

                    //在一条线上if (parent->_left == cur){//情况2,叔叔节点不存在或者存在是黑色的//右单旋RotaR(grandfater);parent->_color = BLACK;grandfater->_color = RED;}

 

情况3:cur为红(插入或者调整后和父亲祖父为线一条折),parent红色,叔叔不存在或者叔叔是黑色,祖父是红色。

uncle不存在:

 uncle存在:

                      if(cur == parent->_left){//情况3,叔叔节点存在是黑色的,在一条折线上RotaL(parent);RotaR(grandfater);cur->_color = BLACK;grandfater->_color = RED;}

●父亲在祖父的右,叔叔在祖父的左:

处理大思路和上述一致,只是叔叔和父亲交换了位置,不在画图分析,列举处理要点:
情况1:叔叔存在且为红色,叔叔和父亲变黑,祖父变红。向上继续查找。

                if (uncle && uncle->_color == RED){//情况1,叔叔存在且是红色parent->_color = uncle->_color = BLACK;grandfater->_color = RED;//继续向上更新cur = grandfater;parent = cur->_parent;}

情况2:叔叔不存在或者存在为黑色,cur的位置和父亲祖父是一条直线,右边高,以祖父为轴点左单旋。祖父变红,父亲变黑。

                   //在右边插入if (parent->_right == cur){//进行一个左单旋RotaL(grandfater);//父亲的颜色变成黑色parent->_color = BLACK;//祖父的的颜色变成红色grandfater->_color = RED;}

情况3:叔叔不存在或者存在为黑色,cur的位置和父亲祖父是一条折线,先以父亲为轴右单旋,以祖父为轴点左单旋祖父变红,cur变黑。

                    if(cur == parent->_left)//左边插入{//右单旋RotaR(parent);//左单旋RotaL(grandfater);//改变颜色grandfater->_color = RED;cur->_color = BLACK;}

测试部分

因为红黑树是二叉搜索树,在测试时很可能会有隐式的错误,比较难发现,所以需要下面的测试接口对红黑树的特性进行检查,检查是否有连续的红色节点出现,每条路径上的黑色节点是否相等

bool check(Node* root,int num,int BLACKNUM){if (root == nullptr){if (num != BLACKNUM){cout << "某条路径上的黑色节点和其他路径不相等" << endl;return false;}return true;}if (root->_color == RED && root->_parent->_color == RED){cout << "连续出现两个红色节点" << endl;return false;}if (root->_color == BLACK){num++;}return check(root->_left, num, BLACKNUM)&&check(root->_right, num, BLACKNUM);}bool IsBalance(){if (_root == nullptr){return false;}//根节点的颜色一定要是黑色if (_root->_color != BLACK){return false;}Node* ret = _root;int _blacknum = 0;while (ret){if (ret->_color == BLACK){_blacknum++;}ret = ret->_left;}return check(_root,0,_blacknum);}

整体代码

#include <time.h>
enum Color
{RED,BLACK
};template<class K,class V>
struct RBTreeNode
{RBTreeNode* _left;RBTreeNode* _right;RBTreeNode* _parent;pair<K, V> _kv;Color _color;RBTreeNode(pair<K, V> kv, Color color = RED):_left(nullptr),_right(nullptr),_parent(nullptr),_kv(kv),_color(color){}
};template <class K,class V>
class RBTee
{
public:typedef RBTreeNode<K,V> Node;bool inster(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);_root->_color = BLACK;return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else{return false;}}//插入节点的位置cur = new Node(kv);cur->_color = RED;if (parent->_kv.first > kv.first){parent->_left = cur;cur->_parent = parent;}else{parent->_right = cur;cur->_parent = parent;}//插入的节点默认是红色的while (parent && parent->_color == RED){Node* grandfater = parent->_parent;if (parent == grandfater->_left){Node* uncle = grandfater->_right;if (uncle && uncle->_color == RED){//情况1,叔叔节点存在,且是红色的parent->_color = uncle->_color = BLACK;grandfater->_color = RED;//更新cur和parent的位置cur = grandfater;parent = cur->_parent;}else {//左边新增if (parent->_left == cur){//情况2,叔叔节点存在是黑色的,在一条线上//右单旋RotaR(grandfater);parent->_color = BLACK;grandfater->_color = RED;}//右边新增else{//情况3,叔叔节点存在是黑色的,在一条折线上RotaL(parent);RotaR(grandfater);cur->_color = BLACK;grandfater->_color = RED;}//树进行了旋转调整,已经平衡,跳出循环break;}}else //parent在grandfater的右边{Node* uncle = grandfater->_left;if (uncle && uncle->_color == RED){//情况1,叔叔存在且是黑色parent->_color = uncle->_color = BLACK;grandfater->_color = RED;//继续向上更新cur = grandfater;parent = cur->_parent;}else//uncle的颜色是黑色{//在右边插入if (parent->_right == cur){//进行一个左单旋RotaL(grandfater);//父亲的颜色变成黑色parent->_color = BLACK;//祖父的的颜色变成红色grandfater->_color = RED;}else//左边插入{//右单旋RotaR(parent);//左单旋RotaL(grandfater);//改变颜色grandfater->_color = RED;cur->_color = BLACK;}break;}}}_root->_color = BLACK;return true;}void Inorder(){_Inorder(_root);}bool check(Node* root,int num,int BLACKNUM){if (root == nullptr){if (num != BLACKNUM){cout << "某条路径上的黑色节点和其他路径不相等" << endl;return false;}return true;}if (root->_color == RED && root->_parent->_color == RED){cout << "连续出现两个红色节点" << endl;return false;}if (root->_color == BLACK){num++;}return check(root->_left, num, BLACKNUM)&&check(root->_right, num, BLACKNUM);}bool IsBalance(){if (_root == nullptr){return false;}//根节点的颜色一定要是黑色if (_root->_color != BLACK){return false;}Node* ret = _root;int _blacknum = 0;while (ret){if (ret->_color == BLACK){_blacknum++;}ret = ret->_left;}return check(_root,0,_blacknum);}
private:void _Inorder(Node* root){if (root == nullptr){return ;}_Inorder(root->_left);cout << root->_kv.first << ":" << root->_kv.first << endl;_Inorder(root->_right);}void RotaL(Node* pparent){Node* subR = pparent->_right;Node* subRL = subR->_left;pparent->_right = subRL;if (subRL){subRL->_parent = pparent;}Node* pNode = pparent->_parent;pparent->_parent = subR;subR->_left = pparent;if (pNode == nullptr){_root = subR;_root->_parent = nullptr;}else{if (pNode->_left == pparent){pNode->_left = subR;}else if (pNode->_right == pparent){pNode->_right = subR;}subR->_parent = pNode;}}void RotaR(Node* pparent){Node* subL = pparent->_left;Node* subLR = subL->_right;pparent->_left = subLR;if (subLR != nullptr){subLR->_parent = pparent;}Node* pNode = pparent->_parent;subL->_right = pparent;pparent->_parent = subL;if (pNode == nullptr){_root = subL;_root->_parent = nullptr;}else{if (pNode->_left == pparent){pNode->_left = subL;}else{pNode->_right = subL;}subL->_parent = pNode;}}private:Node* _root = nullptr;
};

http://www.hkea.cn/news/802346/

相关文章:

  • 个体营业执照可以做网站搞推广吗推广网站制作
  • 公共交通公司网站建设方案移动慧生活app下载
  • 国内开源代码网站搜了网推广效果怎么样
  • html5 metro风格网站模板今日新闻事件
  • 网站不在首页显示出来做网络推广
  • 上海网站seo公司网页推广平台
  • 网站服务器租用价格表百度怎么发布自己的广告
  • 经纪人做网站技巧搜索引擎入口yandex
  • 教育网站制作哪家服务好全球外贸采购网
  • 响应式网络网站源码百度关键词查询网站
  • 南京网站制作设计公司网络运营团队
  • 阿里巴巴上怎样做自己的网站seo网站优化网站编辑招聘
  • 网站做付费推广都需要问什么网络热词2022
  • 给男票做网站表白的软件产品市场推广计划书
  • 西安网站制作定制怎么制作自己的个人网站
  • wordpress 如何移动端盐城seo优化
  • asp.net 制作网站开发百度竞价排名软件
  • 百度爱采购推广平台天津网络推广seo
  • 福州市闽侯县建设局网站推广引流吸引人的文案
  • wordpress目录 读写权限泰安短视频seo
  • 东莞建设网站流程澎湃新闻
  • 萧县住房和城乡建设局网站seo排名推广工具
  • 企业网站php模板下载百度百科官网首页
  • 做愛視頻网站在线网页制作网站
  • 织梦pc怎么做手机网站搜索引擎优化的基础是什么
  • 课程建设网站设计源码爱站网反链查询
  • 安徽省建设业协会网站个人网页制作教程
  • 好的摄影网站推荐福州seo顾问
  • html做的好看的网站如何宣传推广产品
  • 微信手机网站制作怎么引流客源最好的方法