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

广元网站建设广元企业邮箱注册申请要钱吗

广元网站建设广元,企业邮箱注册申请要钱吗,网站免费正能量直接进入浏览器下载安装,page 编辑 wordpress文章目录引入key-value模型map和set底层setset的几个重要接口mapmap几个重要的接口map和set的封装引入 对于map和set的引入,我们用一道在程序中常见的问题解决: 给定一个数组int arr[]{1,2,1,3,1,4,1,5,5,2,3,4,5};,给出以下问题的解决方案&…

文章目录

  • 引入
    • key-value模型
    • map和set底层
  • set
    • set的几个重要接口
  • map
    • map几个重要的接口
  • map和set的封装

引入

对于map和set的引入,我们用一道在程序中常见的问题解决:
给定一个数组int arr[]={1,2,1,3,1,4,1,5,5,2,3,4,5};,给出以下问题的解决方案:

  1. 找出出现次数最多的元素
  2. 去除数组中重复的元素,并输出(任意顺序)

这些问题在没有学习map和set之前并没有很好的解决方法(但是map和set并不是唯一的解决方法),第二个问题:之前我们解决的方法一般就开辟一个新数组tmp,遍历arr中所有元素,对于arr中任意元素遍历tmp数组如果元素在tmp中未出现就插入。第一个问题,只需将数组类型改成一个结构体,该结构体包含一个元素和他出现的次数,则在最后一步如果arr中元素已经出现在tmp中,就改变tmp中该元素对应结构体的次数。

我们发现arr在tmp中插入时每一次都要遍历一遍tmp数组,是否能提升查找效率呢?

所以我们现在需要一个容器:

  • 该容器中不存在重复元素
  • 该容器中查找一个元素效率要高

key-value模型

key-value模型适用于上面的问题1,每一个元素(key)和他出现的次数(value)一 一对应,但是每次查找tmp数组,都是以key为依据查找。
举个例子:一个英汉字典就是典型的key-value模型,英文(key)是你搜索的依据,中文(value)是查找的内容,两者一一对应

map和set底层

有一个数据结构完美符合上面我们需要容器的两个条件——红黑树。首先红黑树不能插入重复元素,所以可以做到去重的效果。又因为满足二叉搜索树所以查找效率比高。而且比二叉搜索树稳定。所以map和set的底层采用的是红黑树

set

set存储元素的类型为key,容器中将该类型定义为value_type

set的几个重要接口


  • insert
     pair<iterator,bool> insert (const value_type& val);pair<iterator,bool> insert (value_type&& val);
    
    注意insert的返回值是一个pair类型,first是插入元素的迭代器(如果val在set中不存在返回插入新元素的迭代器,如果在set中存在返回set中值为val的那个元素的迭代器),second代表是否插入成功

  • operator++
    由于set底层采用的是红黑树,迭代器++则采用的是树的中序遍历,所以遍历的结果应该是一个有序数组

map

map中存储的元素的类型是:pair<key,value>,容器中将该类型定义为value_type

map几个重要的接口


  • insert
    pair<iterator,bool> insert (const value_type& val);
    template <class P> 
    pair<iterator,bool> insert (P&& val);
    
    返回值
    注意insert的返回值是一个pair类型,first是插入元素的迭代器(如果val在set中不存在返回插入新元素的迭代器,如果在set中存在返回set中值为val的那个元素的迭代器),second代表是否插入成功

  • find
    iterator find (const key_type& k);
    const_iterator find (const key_type& k) const;
    
    返回值
    如果找到了返回该元素的迭代器,找不到返回map::end()

  • operator[]
    mapped_type& operator[] (const key_type& k);
    mapped_type& operator[] (key_type&& k);
    
    这里mapped_type是我们map中存储元素类型pair<key,value>中的value
    这个运算符重载给我们map的使用带来了巨大的方便,map[key](map.insert(key,value()).first)->second是等价的。

  • operator++
    由于map底层采用的是红黑树,迭代器++则采用的是树的中序遍历,所以遍历的结果应该是一个有序数组

map和set的封装

我们对于map和set封装始终是在红黑树的基础上进行封装的,红黑树的代码可以参考blog红黑树
红黑树的代码接下来的封装都是在这个代码的基础上进行修改的!
封装的结构为:
在这里插入图片描述

这里以map的封装为例: map的封装弄明白了,set就非常简单了
首先需要将红黑树的节点模板改一下:
在这里插入图片描述
这里修改后使得树节点里面存储的是ValueType类型,ValueType类型实际上就是修改前pair<K,V>,我们可以发现ValueType实际上就是我们在外层插入时插入时传进去的类型

template <class ValueType>struct TreeNode{};template <class K, class ValueType, class GetKey>    
class RBTree{};

那么问题来了:

  • 已经传入了ValueType为什么要传入K?
    传入Key类型只是作为返回值类型,因为find函数参数为const K& x,仅此而已。

  • 红黑树在插入搜索时需要比较key值,节点里面存储的是ValueType,如何比较?
    有些同学会认为很简单,直接(ValueType)x.second不就行了?这样确实可以,但是没有考虑一个问题set也需要使用这份红黑树代码作为底层,如果用上面的代码,set中的ValueTypeK是同一个类型,这时就会出现错误。
    我们的解决方法是使用仿函数Get_key来取出ValueType中的Value,让上层来决定如何取出方法。这就是仿函数的妙处

剩下来只需要将红黑树中函数封装到上层map中就可以了


#include "RedBlackTree.h"
#include <utility>namespace sht
{template <class Key, class Value>class map{struct Get_Key_From_ValueType{Key operator()(const std::pair<Key, Value> &v){return v.first;}};public:typedef std::pair<const Key, Value> ValueType;    //注意这里定义的ValueType是实际树节点里面存的内容typedef typename sht::RBTree<Key, ValueType, Get_Key_From_ValueType>::iterator iterator;typedef typename sht::RBTree<Key, ValueType, Get_Key_From_ValueType>::const_iterator const_iterator;std::pair<iterator,bool> insert(const std::pair<Key, Value> x){return tree.insert(x);}Value&  operator [](const Key& x){auto ret = tree.insert(std::make_pair(x, Value()));return (ret.first)->second;}const_iterator begin() const // 常量迭代器{return tree.begin();}const_iterator end() const{return tree.end();}iterator begin() // 普通迭代器 : 注意普通迭代器的key也是无法修改的{return tree.begin();}iterator end(){return tree.end();}private:sht::RBTree<Key, ValueType, Get_Key_From_ValueType> tree;};
}

这里map还有一个设计的技巧如果是const对象,那么beginend要返回const迭代器,这里重载了begin和end函数(参考这篇blog)。这个设计很巧妙😋

接下来是一个硬骨头:迭代器的设计

   template <class T, class ptr, class ref>   //ref是class RBTreeiterator{public:typedef TreeNode<T> Node;typedef RBTreeiterator<T, ptr, ref> Self;RBTreeiterator(Node *x=nullptr){p = x;}//迭代器的运算符重载Self &operator++();Self &operator--();bool operator==(const RBTreeiterator &x)bool operator!=(const RBTreeiterator &x)T operator*()ptr operator->()     Node *p;};

然而一个问题出现了,非const对象想要使用const迭代器时就会出现问题:
例如:map<int,int>::const_iterator it=x.begin();这时就会报错,因为是非const对象,调用的begin是非const成员函数,返回的是普通迭代器,所以报错的原因是缺乏普通迭代器到const迭代器的转化!!
在这里插入图片描述
重写一个拷贝构造函数就完美解决了,在迭代器里面的iterator巧妙的构造出了普通迭代器类型,很巧妙的解决了该问题

迭代器的运算符重载中还有一个难点是operator ++——即按中序取当前节点的下一个节点,这种问题参考LeetCode剑指 Offer II 055. 二叉搜索树迭代器,我这里就不赘述了。

http://www.yayakq.cn/news/426148/

相关文章:

  • 贵阳网站制作专业网站开发图书系统前台模板
  • 网站在线压缩wordpress获取分类文章
  • 来宾北京网站建设建立简单网站
  • 有一个做5s壁纸的网站做外贸有什么免费网站
  • 手机网站建设万网合肥做机床的公司网站
  • 品牌网站建设黑白I狼J网站建设费用包括哪些方面
  • app网站开发小程序网络营销的50种方法
  • 徐汇制作网站哪家好华为免费企业网站建设
  • 饶平网站建设如何优化网站首页代码
  • 网站建设网页设计公司长沙市公共资源交易中心
  • 西宁高端网站建设公司升学历有哪几种报名方式
  • 网站制作有限公司设计门户网站
  • 国外创意网站设计欣赏灵雀云 wordpress
  • 国外做二手服装网站有哪些租用海外服务器的网站有域名吗
  • 景区宣传网站制作模板如何做网络营销推广啃26金手指效果牛x
  • 石家庄网站制作工具成都网站seo推广
  • 网站设计培训课程怎样制作网站建设规划图
  • 跨境网站有哪些平台做网站都有备案吗
  • 二手车网站策划网站建设的五类成员
  • 音乐影视网站建设方案女装商城网站建设
  • 广州官网建站深圳 网页设计公司
  • 网站备案 每年做360手机网站首页
  • 注册域名成功后怎样建设网站免费网页在线代理服务器
  • 招代理网站建设公司高端轻奢品牌
  • 一诺互联网站建设公司自己做的网站算广告吗
  • 动易网站风格免费下载做网站报价单
  • 电商网站的付款功能一键wordpress建站
  • 百度提交收录入口广州市口碑seo推广
  • 无锡企业网站制作公司网站建设设计公司 知乎
  • 长沙装修网站排名一个好的网站应该具有什么