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

武汉网站建设公司有哪些百度提交网站收录入口

武汉网站建设公司有哪些,百度提交网站收录入口,网站开发项目经理主要工作,政府网站html源码在STL的源代码中&#xff0c;map和set的底层原理都是红黑树。但这颗红黑树跟我们单独写的红黑树不一样&#xff0c;它需要改造一下&#xff1a; 改造红黑树 节点的定义 因为map和set的底层都是红黑树。而且map是拥有键值对pair<K,V>的&#xff0c;而set是没有键值对&a…

在STL的源代码中,map和set的底层原理都是红黑树。但这颗红黑树跟我们单独写的红黑树不一样,它需要改造一下:

改造红黑树

节点的定义

因为map和set的底层都是红黑树。而且map是拥有键值对pair<K,V>的,而set是没有键值对,只有一个K。因此,为了应对这两种不同的情况,就使用模板参数T。

当map使用这棵红黑树的时候,T就会变成pair<K,V>。当set使用时,T就会变成K。

//使用枚举
enum Colour
{RED,BLACK,
};// 如果是map,则为pair<K, V>; 如果是set,则为k
//因此,对于节点来说,需要再套一层模板,来应付两种不同的情况
template<class T>
struct RBTreeNode
{T _data;RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;Colour _col;RBTreeNode(const T& data):_data(data), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED)  //默认是红色{}
};

改版的红黑树的插入操作

红黑树的模板参数有三个:K、valueType和仿函数KeyOfValue。

K是key的类型,ValueTyp要么是set的K,要么是map的pair<const K,V>。

而仿函数是为了比较节点的值的大小的,因为官方库中键值对pair<K,V>比较大小的方法是比较first和second。但是红黑树中,新增节点是通过比较first,因此我们需要自己写一个仿函数用于单独比较first。

//跟节点的定义一样
//因为关联式容器中存储的是<key, value>的键值对,因此
// k为key的类型,
// ValueType: 如果是map,则为pair<K, V>; 如果是set,则为k。如下:
// map->RBTree<K,pair<const K,V>,MapKeyOfT> _t;
// set->RBTree<K,K,SetKeyOfT> _t
// 
// KeyOfValue: 通过value来获取key的一个仿函数类。其作用就是用于比较。
template<class K,class ValueType,class KeyOfValue>
class RBTree
{typedef RBTreeNode<ValueType> Node;
public: //迭代器typedef __RBTreeIterator<ValueType> iterator;//......
private:Node* _root = nullptr;
};

迭代器

红黑树的迭代器不能使用原生指针,因为它是一棵树,节点地址不连续,因此需要封装起来。

//set的K,map的pair<K,V>
template<class ValueType>
struct __RBTreeIterator
{typedef RBTreeNode<ValueType> Node;typedef __RBTreeIterator<ValueType> Self;Node* _node;__RBTreeIterator(Node* node):_node(node){}
};

1.operator++()

红黑树是二叉搜索树,采用的是中序遍历的方法。因此,迭代器每次向前走,是按照中序遍历的顺序走的。

因此,对于往前++,有两种情况:第一种情况是当前节点的右孩子不为空,那么按照中序遍历的顺序,下一个节点便是右子树的最小值。第二种情况是当前节点的右孩子为空:这种情况下,又分两种情况:①当前节点是父节点的左孩子,那么下一个节点肯定是当前节点的父节点。②当前节点是父节点的右孩子,这意味着当前节点的父节点也被遍历了,又没有右孩子节点,只能往上找了,找的节点是祖先节点,而这个祖先节点是特征是:孩子节点是它的左节点。

 

	//左 根  右Self& operator++(){//当当前节点的右子树不为空,根据中序遍历的顺序,那就找右子树最小值if (_node->_right){Node* minValue = _node->_right;while (minValue->_left){minValue = minValue->_left;}//找到最小值的节点后,更新节点_node = minValue;}else  //当当前节的的右子树为空,说明它是叶子节点。此时需要判断情况{//判断当前节点是父亲节点的左孩子还是右孩子//第一种情况:如果是cur==parent->_right,即当前节点是父节点的右孩子的话,就//去找祖先节点(这个祖先节点的特征:孩子节点是它的左节点)//第二种情况:当前节点是父亲节点的左孩子,那么下一个节点就是父亲节点了Node* cur = _node;//定义父亲节点。Node* parent = cur->_parent;//如果当前节点不是父亲的右孩子,并且父亲是不存在,那么就是根节点或者是左孩子节点了//那就不进入循环。while (parent && cur == parent->_right){//如果是,那就往上找到下一个节点。cur = cur->_parent;parent = parent->_parent;}//更新节点_node = parent;}return *this;}

2.begin()和end();

迭代器的begin和end,是左闭右开的区间。那么begin就是最左的节点,end则是最右节点的下一个节点。这里不使用哨兵来作为end节点。

对于begin,就找到最左的节点就好啦!

iterator begin(){Node* left = _root;while (left && left->_left){left = left->_left;}return iterator(left);}

对于end,这里选择直接置为空,传入匿名对象。这样子做的话,当遍历到最后一个节点后,它会往回遍历,一直到了根节点的上面一个节点,也就是空。此时就会结束循环。

	iterator end(){return iterator(nullptr);}

迭代器整体代码:

template<class ValueType>
struct __RBTreeIterator
{typedef RBTreeNode<ValueType> Node;typedef __RBTreeIterator<ValueType> Self;Node* _node;__RBTreeIterator(Node* node):_node(node){}ValueType& operator*(){return _node->_data;}ValueType* operator->(){return &_node->_data;}Self& operator++(){if (_node->_right){Node* minValue = _node->_right;while (minValue->_left){minValue = minValue->_left;}_node = minValue;}else {Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_right){cur = cur->_parent;parent = parent->_parent;}_node = parent;}return *this;}bool operator!=(const Self& s){return _node != s._node;}
};

set的模拟实现

仿函数

由于set只有Key,因此就让仿函数直接返回Key值就可以了。

template<class K>class set{//set的仿函数,返回set的K值struct SetKeyOfValue{const K& operator()(const K& key){return key;}};

整体都是复用了红黑树的接口,并没有什么技术含量,问题都在红黑树中解决了。

namespace my_set
{template<class K>class set{//set的仿函数,返回set的K值struct SetKeyOfValue{const K& operator()(const K& key){return key;}};public:typedef typename RBTree<K, K, SetKeyOfValue>::iterator iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}bool insert(const K& key){return _t.Insert(key);}private:RBTree<K, K, SetKeyOfValue> _t;};

map的模拟实现:

仿函数

由于比较的是first,因此我们返回键值对中的first即可。

template<class K, class V>class map{struct MapKeyOfValue{const K& operator()(const pair<const K, V>& kv){return kv.first;}};

整体代码,一样的都是复用了红黑树的接口,并没有什么技术含量:

namespace my_map
{template<class K, class V>class map{struct MapKeyOfValue{const K& operator()(const pair<const K, V>& kv){return kv.first;}};public:typedef typename RBTree<K, pair<const K, V>, MapKeyOfValue>::iterator iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}bool insert(const pair<const K, V>& kv){return _t.Insert(kv);}private:RBTree<K, pair<const K, V>, MapKeyOfValue> _t;};

最后是红黑树的整体代码,这段代码跟单独写的红黑树的代码差不多,就是在新增节点的操作那里,比较节点的值使用的是仿函数。

#pragma once//使用枚举
enum Colour
{RED,BLACK,
};// 如果是map,则为pair<K, V>; 如果是set,则为k
//因此,对于节点来说,需要再套一层模板,来应付两种不同的情况
template<class T>
struct RBTreeNode
{T _data;RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;Colour _col;RBTreeNode(const T& data):_data(data), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED)  //默认是红色{}
};template<class ValueType>
struct __RBTreeIterator
{typedef RBTreeNode<ValueType> Node;typedef __RBTreeIterator<ValueType> Self;Node* _node;__RBTreeIterator(Node* node):_node(node){}ValueType& operator*(){return _node->_data;}ValueType* operator->(){return &_node->_data;}//左 根  右Self& operator++(){//当当前节点的右子树不为空,根据中序遍历的顺序,那就找右子树最小值if (_node->_right){Node* minValue = _node->_right;while (minValue->_left){minValue = minValue->_left;}//找到最小值的节点后,更新节点_node = minValue;}else  //当当前节的的右子树为空,说明它是叶子节点。此时需要判断情况{//判断当前节点是父亲节点的左孩子还是右孩子//第一种情况:如果是cur==parent->_right,即当前节点是父节点的右孩子的话,就//去找祖先节点(这个祖先节点的特征:孩子节点是它的左节点)//第二种情况:当前节点是父亲节点的左孩子,那么下一个节点就是父亲节点了Node* cur = _node;//定义父亲节点。Node* parent = cur->_parent;//如果当前节点不是父亲的右孩子,并且父亲是不存在,那么就是根节点或者是左孩子节点了//那就不进入循环。while (parent && cur == parent->_right){//如果是,那就往上找到下一个节点。cur = cur->_parent;parent = parent->_parent;}//更新节点_node = parent;}return *this;}bool operator!=(const Self& s){return _node != s._node;}
};
//跟节点的定义一样
//因为关联式容器中存储的是<key, value>的键值对,因此
// k为key的类型,
// ValueType: 如果是map,则为pair<K, V>; 如果是set,则为k。如下:
// map->RBTree<K,pair<const K,V>,MapKeyOfT> _t;
// set->RBTree<K,K,SetKeyOfT> _t
// 
// KeyOfValue: 通过value来获取key的一个仿函数类。其作用就是用于比较。
template<class K,class ValueType,class KeyOfValue>
class RBTree
{typedef RBTreeNode<ValueType> Node;
public:typedef __RBTreeIterator<ValueType> iterator;iterator begin(){Node* left = _root;while (left && left->_left){left = left->_left;}return iterator(left);}iterator end(){return iterator(nullptr);}bool Insert(const ValueType& data){//先按二叉搜索树的规矩来创建一棵二叉搜索树if (_root == nullptr){_root = new Node(data);//因为红黑树的根节点是黑色的_root->_col = BLACK;return true;}KeyOfValue kot;Node* parent = nullptr;Node* cur = _root;while (cur){if (kot(cur->_data) < kot(data)){parent = cur;cur = cur->_right;}else if (kot(cur->_data) > kot(data)){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(data);cur->_col = RED;//多写一步,防止写错代码。if (kot(parent->_data) < kot(data)){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}//创建完二叉搜索树//开始创建红黑树,使用颜色来判断是否需要调整//循环往上走,循环条件:当走到的parent不为空,并且parent是红色的//即我们列举是三种情况,parent都是红的,就需要重新调整//如果parent是黑色的,那就不需要了。直接就是一棵红黑树,不进入循环while (parent && parent->_col == RED){//保存祖先节点,即g节点Node* grandfther = parent->_parent;//判断父节点是在祖先节点的哪边if (parent == grandfther->_left){//父节点在左边,那么叔叔节点就在右边Node* uncle = grandfther->_right;//情况一:uncle存在且为红。改变颜色即可if (uncle && uncle->_col == RED){//变色。parent->_col = uncle->_col = BLACK;grandfther->_col = RED;//往上走cur = grandfther;parent = cur->_parent;}else  //uncle不存在 或者 存在但是黑色{//情况二  p是g的左孩子,cur是p的左孩子,以g为轴右单旋if (cur == parent->_left){//右单旋RotateR(grandfther);//变色  右单旋后,parent为根节点,变黑色。cur和g节点为红色parent->_col = BLACK;grandfther->_col = RED;}else  //情况三  p是g的左孩子,cur是p的右孩子.{//先以p为轴左旋转RotateL(parent);//变成情况二,再以g为轴右单旋RotateR(grandfther);//变色  cur变成根节点,为黑色。p和g是红色cur->_col = BLACK;grandfther->_col = RED;}break;}}else  //parent是在grandfther的右边{//叔叔节点就在祖先节点的左边Node* uncle = grandfther->_left;//情况一:uncle存在且为红。改变颜色即可if (uncle && uncle->_col == RED){//变色。parent->_col = uncle->_col = BLACK;grandfther->_col = RED;//往上走cur = grandfther;parent = cur->_parent;}else  //uncle不存在 或者 存在但是黑色{//情况二  p是g的右孩子,cur是p的右孩子。if (cur == parent->_right){//左单旋RotateL(grandfther);//变色  右单旋后,parent为根节点,变黑色。cur和g节点为红色parent->_col = BLACK;grandfther->_col = RED;}else  //情况三  p是g的右孩子,cur是p的左孩子.{//先以p为轴右旋转RotateR(parent);//变成情况二,再以g为轴左单旋RotateL(grandfther);//变色  cur变成根节点,为黑色。p和g是红色cur->_col = BLACK;grandfther->_col = RED;}break;}}}//最后将根节点置为黑_root->_col = BLACK;return true;}void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL){subRL->_parent = parent;}Node* ppNode = parent->_parent;subR->_left = parent;parent->_parent = subR;if (ppNode == nullptr){_root = subR;_root->_parent = nullptr;}else{if (ppNode->_left == parent){ppNode->_left = subR;}else{ppNode->_right = subR;}subR->_parent = ppNode;}}void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR){subLR->_parent = parent;}Node* ppNode = parent->_parent;subL->_right = parent;parent->_parent = subL;if (ppNode == nullptr){_root = subL;_root->_parent = nullptr;}else{if (ppNode->_left == parent){ppNode->_left = subL;}else{ppNode->_right = subL;}subL->_parent = ppNode;}}void Inorder(){_Inorder(_root);}void _Inorder(Node* root){if (root == nullptr)return;_Inorder(root->_left);std::cout << root->_kv.first << ": " << root->_kv.second << std::endl;_Inorder(root->_right);}bool Check(Node* root, int blackNum, const int ref){if (root == nullptr){//cout << blackNum << endl;if (blackNum != ref){cout << "违反规则:本条路径的黑色节点的数量跟最左路径不相等" << endl;return false;}return true;}if (root->_col == RED && root->_parent->_col == RED){cout << "违反规则:出现连续红色节点" << endl;return false;}if (root->_col == BLACK){++blackNum;}return Check(root->_left, blackNum, ref)&& Check(root->_right, blackNum, ref);}bool IsBalance(){if (_root == nullptr){return true;}if (_root->_col != BLACK){return false;}int ref = 0;Node* left = _root;while (left){if (left->_col == BLACK){++ref;}left = left->_left;}return Check(_root, 0, ref);}
private:Node* _root = nullptr;
};


文章转载自:
http://reexperience.c7495.cn
http://fourply.c7495.cn
http://nutate.c7495.cn
http://decimal.c7495.cn
http://cheaters.c7495.cn
http://pyaemia.c7495.cn
http://jacobin.c7495.cn
http://nonflammable.c7495.cn
http://inductivism.c7495.cn
http://encyclic.c7495.cn
http://effectually.c7495.cn
http://rdb.c7495.cn
http://insincerely.c7495.cn
http://harken.c7495.cn
http://snowcapped.c7495.cn
http://qea.c7495.cn
http://queenside.c7495.cn
http://nelumbo.c7495.cn
http://oos.c7495.cn
http://nasopharynx.c7495.cn
http://peloponnesian.c7495.cn
http://cattery.c7495.cn
http://clottish.c7495.cn
http://funereal.c7495.cn
http://plum.c7495.cn
http://parma.c7495.cn
http://pricker.c7495.cn
http://element.c7495.cn
http://derriere.c7495.cn
http://coralliferous.c7495.cn
http://aeromarine.c7495.cn
http://fagmaster.c7495.cn
http://litek.c7495.cn
http://opalescent.c7495.cn
http://dumping.c7495.cn
http://holland.c7495.cn
http://taligrade.c7495.cn
http://frostbiter.c7495.cn
http://honky.c7495.cn
http://chloralose.c7495.cn
http://samite.c7495.cn
http://antitank.c7495.cn
http://askari.c7495.cn
http://whiffet.c7495.cn
http://boh.c7495.cn
http://audibility.c7495.cn
http://wctu.c7495.cn
http://tenseless.c7495.cn
http://subovate.c7495.cn
http://interus.c7495.cn
http://apothecary.c7495.cn
http://lubricative.c7495.cn
http://coproantibody.c7495.cn
http://ultramodern.c7495.cn
http://redemptory.c7495.cn
http://ruralist.c7495.cn
http://sylvester.c7495.cn
http://pycnogonid.c7495.cn
http://interact.c7495.cn
http://hanaper.c7495.cn
http://aspheric.c7495.cn
http://winesap.c7495.cn
http://dethronement.c7495.cn
http://eventually.c7495.cn
http://leatherworking.c7495.cn
http://dissociate.c7495.cn
http://epicedium.c7495.cn
http://reinhabit.c7495.cn
http://banjoist.c7495.cn
http://alligatorfish.c7495.cn
http://year.c7495.cn
http://totemic.c7495.cn
http://parnassus.c7495.cn
http://reast.c7495.cn
http://halcyone.c7495.cn
http://prename.c7495.cn
http://eudemonia.c7495.cn
http://ayin.c7495.cn
http://emblematical.c7495.cn
http://catagmatic.c7495.cn
http://asshead.c7495.cn
http://shovelnose.c7495.cn
http://tumultuous.c7495.cn
http://conventionalise.c7495.cn
http://pickproof.c7495.cn
http://fluvialist.c7495.cn
http://ayahuasca.c7495.cn
http://npr.c7495.cn
http://bask.c7495.cn
http://cystourethrography.c7495.cn
http://bedtiime.c7495.cn
http://gummatous.c7495.cn
http://leery.c7495.cn
http://huzzy.c7495.cn
http://validly.c7495.cn
http://degerm.c7495.cn
http://majorca.c7495.cn
http://paean.c7495.cn
http://swagger.c7495.cn
http://adrastus.c7495.cn
http://www.zhongyajixie.com/news/68333.html

相关文章:

  • 手机网站如何做优化长沙网站seo优化公司
  • 网页代理最干净最悠久河南seo快速排名
  • 办公室效果图深圳seo博客
  • 合肥专业的房产网站建设优化教程
  • 建一个公司网站外贸营销网站建设介绍
  • 四川省城乡建设厅网站杭州seo网站排名优化
  • 昆明市做网站公司长沙百度
  • 百度网站排名抓取规则优化课程体系
  • 朝阳区住房和城乡建设委员会官方网站百度快照推广排名
  • 查询公司信息去哪里查搜索引擎环境优化
  • wordpress免签抖音seo关键词优化怎么做
  • 自己做网站吗企业推广网络营销
  • 快速建站视频渠道销售怎么找客户
  • 东莞网站建设制作公司seo爱站网
  • wordpress分类目录置顶广州seo网站营销
  • 反钓鱼网站建设期福建seo网站
  • 日本做设计的网站有哪些衡阳seo优化首选
  • 微信小程序里的网站怎么做互联网推广平台
  • 做的好的地方网站百度招聘官网首页
  • 网站建设竞价托管服务百度竞价推广开户内容
  • 专业移动网站建设商培训班招生方案有哪些
  • 非公党委网站的建设网络营销方案ppt
  • 建立团购网站交换友情链接推广法
  • wordpress设置标题字体大小seo免费自学的网站
  • 自己写代码做网站纹身网站设计
  • 网站建设能带来流量么最近一周新闻大事件
  • 263企业邮箱报价天津seo优化公司哪家好
  • 网站设计定制多少钱竞价网站
  • 通用wap网站生成系统企业类网站有哪些例子
  • 全国b2c网站建设b站视频推广网站动漫