stl源码剖析 详细学习笔记 算法(2)

STL源码剖析——STL算法之merge合并算法 本文介绍的STL算法中的merge合并算法,源码中介绍了函数merge、inplace_merge。并对这些函数的源码进行详细的剖析,并适当给出使用例子。 阅读详情

//---------------------------15/03/29----------------------------

    

    //****************************set相关算法*****************************

    /*

        1>set相关算法一共有4种:并集(union),交集(intersection),差集(difference),

        对称差集(symmetric difference)。

        2>set相关算法只接受set/multiset。

        3>每个算法都是根据 “<”(可以自行定义) 来确定大小 以及是否相等。

        4>这四个算法都是稳定算法,执行后元素的相对顺序不会改变

                                                                            */

    

    //set_union

    //并集就是除了一样的不加 其它的通通塞到Output迭代器中去,所以比较大小,把

    //小的都塞进去,碰到相等的,塞一个进去。最后可能两个迭代器中有一个还有剩余,

    //就把剩余的都拷贝到 输出区间

    template<class InputIterator1, class InputIterator2, class OutputIterator>

    OutputIterator set_union(InputIterator first1, InputIterator last1,

                            InputIterator first2, InputIterator last2,

                            OutputIterator result)

    {

        while (first1 != last1 && first2 != last)

        {

            if (*first1 < *first2) //自定义版本是这样的: if(comp(*first1, *first2))

            {

                *result = *first1;

                ++first1;

            }

            else if(*first2 < *first1)//自定义版本:  if(comp(*first2, *first1))

            {

                *result = *first2;

                ++first2;

            }

            else

            {

                *result = *first1;

                ++first1;

                ++first2;

            }

            ++result;

        }

        return copy(first2, last2, copy(first1, last1, result));

    }

    

    //set_intersection

    //交集么只要取相等的元素,遇到不相等情况的,只要把小的那自加即可。最后就算那个区间有多也可以不管了。

    template<class InputIterator1, class InputIterator2, class OutputIterator>

    OutputIterator set_intersection(InputIterator first1, InputIterator last1,

                                    InputIterator first2, InputIterator last2,

                                    OutputIterator result)

    {

        while (first1 != last1 && first2 != last2)

        {

            if(*first1 < *first2)

                ++first1;

            else if(*first2 < *first1)

                ++first2;

            else

            {

                *result = *first1;

                ++first1;

                ++first2;

                ++result;

            }

        }

        return result;

    }

    //set_difference

    //差集则只要考虑区间1中有的,区间2中没有的,1中小于2的元素可以输出,碰到相等的就让

    //两个区间的都自加,2中小于1的并没有意义,只需让2自加即可,最后1中有剩余的输出,不用考虑2剩余的情况

    template<class InputIterator1, class InputIterator2, class OutputIterator>

    OutputIterator set_difference(InputIterator first1, InputIterator last1,

                             InputIterator first2, InputIterator last2,

                             OutputIterator result)

    {

        while (first1 != last1 && first2 != last2)

        {

            if(*first1 < *first2)

            {

                *result = *first;

                ++first1;

                ++result;

            }

            else if(*first2 < *first1)

                ++first2;

            else

            {

                ++first1;

                ++first2;

            }

        }

        return copy(first, last1, result);

    }

    

    //set_symmetric_difference

    //对称差集,只有相等的情况不输出,所以碰到相等的 两个区间都自加,剩下情况的都输出。

    //最后会有一个区间有多,也要都输出

    template<class InputIterator1, class InputIterator2, class OutputIterator>

    OutputIterator set_difference(InputIterator first1, InputIterator last1,

                                  InputIterator first2, InputIterator last2,

                                  OutputIterator result)

    {

        while (first1 != last1 && first2 != last2)

        {

            if(*first1 < *first2)

            {

                *result = *first1;

                ++first1;

                ++result;

            }

            else if(*first2 < *first1)

            {

                *result = *first2

                ++first2;

                ++result;

            }

            else

            {

                ++first1;

                ++first2;

            }

        }

        return copy(first2, last2, copy(first1, last1, result));

    }

    

    //****************************set相关算法*****************************

    

    //****************************其它算法*****************************

    

    //adjacent_find

    //找到第一组 满足条件(默认是 ==)的 相邻元素

    template<class ForwardIterator>

    ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last)

    {

        if (first == last)

            return last;

        ForwardIterator next = first;

        while (++next != last)

        {

            if(*first == *next)     //自己定义版本 if(binary_pred(*first, *next))

                return first;

            first = next;

        }

        return last;

    }

    

    //count

    //找到与传入的value相等的元素的个数

    template<class InputIterator, class T>

    typename iterator_traits<InputIterator>::difference_type

    count(InputIterator first, InputIterator last, const T& value)

    {

        typename iterator_traits<InputIterator>::difference_type n =0;

        for(; first != last; ++first)

            if(*first == value)     //count_if版本 if( pred(*first))

                ++n;

        return n;

    }

    

    //find

    //找到第一个符合条件的元素

    template<class InputIterator, class T>

    InputIterator find(InputIterator first, InputIterator last,

                       const T& value)

    {

        //find_if版本 while(first != last && !pred(*first))

        while(first != last && *first != value)

            ++first;

        return first;

    }

    

    //find_end

    //找到区间1中最后一组 和区间2 相同的元素

    //如果可以从队尾开始搜索可以快很多,所以分两种情况,可以后退的迭代器,不能后退的迭代器

    template<class ForwardIterator1, class ForwardIterator2>

    inline ForwardIterator1

    find_end(ForwardIterator1 first1, ForwardIterator1 last1,

             ForwardIterator2 first2, ForwardIterator2 last2)

    {

        typedef typename iterator_traits<ForwardIterator1>::iterator_category

            category1;

        typedef typename iterator_traits<ForwardIterator2>::iterator_category

            category2;

        return __find_end(first1, last1, first2, last2, category1(), category2());

    }

    

    template<class ForwardIterator1, class ForwardIterator2>

    ForwardIterator1 __find_end(ForwardIterator1 first1, ForwardIterator1 last1,

                                ForwardIterator2 first2, ForwardIterator2 last2,

                                forward_iterator_tag, forward_iterator_tag)

    {

        if(first2 == last2)

            return last1;

        else

        {

            ForwardIterator1 result = last1;

            while (1)

            {

                //先搜索下一组,再把下一组赋给result  就和单链表删除节点一样,要删除下一个节点,

                //我们要预留上一个节点,这里是要先找到 下一个不符合的情况 我们才知道这是最后一个

                ForwardIterator1 new_result = search(first1, last1, first2, last2);

                if(new_result == last1)

                    return result;

                else

                {

                    result = new_result;

                    first1 = new_result;

                    ++first;

                }

            }

        }

    }

    

    //双向迭代器走这边

    template<class BidirectionalIterator1, class BidirectionalIterator2>

    BidirectionalIterator1

    __find_end(BidirectionalIterator1 first1, BidirectionalIterator1 last1,

               BidirectionalIterator2 first2, BidirectionalIterator2 last2,

               bidirectional_iterator_tag, bidirectional_iterator_tag)

    {

        typedef reverse_iterator<BidirectionalIterator1> reviter1;

        typedef reverse_iterator<BidirectionalIterator2> reviter2;

        

        //先确定end位置

        reviter1 rlast1(first1);

        reviter2 rlast2(first2);

        

        //找到第一组就可以了

        reviter1 rresult = search(reviter1(last1), rlast1,

                                  reviter2(last2), rlast2);

        

        if(rresult == rlast1)

            return last1;       //没找到

        else

        {

            //修改位置, base()成员函数可以取得真实位置,因为反向迭代器有两个位置,

            //一个是真实位置,一个是他 “下一个”位置 他的”下一个“其实是正向迭代器的上一个

            //1 2 3 此时反向迭代器指向3 operator*() 取到的是2 base()取到的是 3

            //下面的操作是为了使result == end

            BidirectionalIterator1 result = rresult.base();

            //减去距离,就可以使result变成first

            advance(result, -distance(first2, last2));

            return result;

        }

    }

    

    //find_first_of

    //在区间1中找到 第一个 与区间2中 任意元素匹配 的位置

    template<class InputIterator, class ForwardIterator>

    InputIterator find_first_of(InputIterator first1, InputIterator last1,

                                ForwardIterator first2, ForwardIterator last2)

    {

        for(; first1 != last1; ++first1)

            for(ForwardIterator iter = first2; iter != last2; ++iter)

                if(*first1 == *iter)        //自定义版本 if(comp(*first, *last))

                    return first;

        return last1;

    }

    

    //for_each

    //对每个元素调用仿函数f

    template<class InputIterator, class Function>

    Function for_each(InputIterator first, InputIterator last, Function f)

    {

        for(; first != last; ++first)

            f(*first);

        return f;

    }

    

    //generate

    //把仿函数的返回值填充区间。相当于:  auto rel=gen(); fill(first, last, rel);

    template<class ForwardIterator, class Generator>

    void generate(ForwardIterator first, ForwardIterator last, Generator gen)

    {

        for(; first != last; ++first)

            *first = gen();

    }

    

    //填充n个 gen()

    template<class OutputIterator,class Size, class Generator>

    OutputIterator generate_n(OutputIterator first, Size n, Generator gen)

    {

        for(; n > 0; --n, ++first)

            *first = gen();

        return first;

    }

    

    //includes 应用于有序的区间

    //依次找,只要区间1的元素 小于等于 区间二就继续下去 一旦区间2中的元素小于区间1的

    //说明这个数 在区间1中 就找不到和他相等的数了,就可以返回false了

    template<class InputIterator1, class InputIterator2>

    bool includes(InputIterator1 first1, InputIterator1 last1,

                  InputIterator2 first2, InputIterator2 last2)

    {

        while (first1 != last1 && first2 != last2)

        {

            if(*first2 < *first1)   //自定义版本:if(comp(*first2, *first1))

                return false;

            else if(*first1 < *first2) //自定义版本:if(comp(*first1, *first2))

                ++first1;

            else

                ++first1, ++first2;

        }

        return first2 == last2;

    }

    

    //max_element

    template<class ForwardIterator>

    ForwardIterator max_element(ForwardIterator first, ForwardIterator last)

    {

        if(first == last)

            return first;

        ForwardIterator result = first;

        while(++first != last)

            if(*result < *first)        //自定义版本: if(comp(*result, *first))

                result = first;

        return result;

    }

    

    //merge 要求有序

    template<class InputIterator1, class InputIterator2, class OutputIterator>

    OutputIterator merge(InputIterator1 first1, InputIterator1 last1,

                         InputIterator2 first2, InputIterator2 last2,

                         OutputIterator result)

    {

        while (first1 != last1 && first2 != last2)

        {

            if(*first2 < *first1)   //自定义版本: if(comp(*first2, *first1))

            {

                *result = *first2;

                ++first2;

            }

            else

            {

                *result = *first1;

                ++first1;

            }

            ++result;

        }

        return copy(first2, last2, copy(first1, last1, result));

        

    }

STL源码剖析——list容器的排序算法sort() 由于STL本身的排序算法sort接受的输入迭代器是随机访问迭代器,但是双向list链表容器的访问方式是双向迭代器,因此,不能使用STL本身的排序算法sort,必须自己定义属于自己访问的排序算法。我们从源码的剖析中,可以看到该排序算法思想类似于归并排序。 阅读详情

相关推荐

STL源码剖析——STL算法之remove删除算法

本文介绍的STL算法中的remove删除算法,源码中介绍了函数remove、remove_copy、remove_if、remove_copy_if、unique、unique_copy。并对这些函数的源码进行详细的剖析,并适当给出使用例子。

关注校招求职,微信号:job_campus 2036

反向迭代器reverse_iterator与正向迭代器iterator之间的转换(以及实例应用)

反向迭代器     相信大家对正向迭代器应该都很熟悉,然而对于反向迭代器的使用确是有几处需要注意的地方,在此记录一下。先看STL源码处注释如下:   /** * Bidirectional and random access iterators have corresponding reverse * %iterator adaptors that iterate th...

weixin_40311211的博客 1万+

STL源码剖析——STL算法之find查找算法

本文介绍的STL算法中的find、search查找算法。在STL源码中有关算法的函数大部分在本文介绍,包含findand find_if、adjacent_find、search、search_n、lower_bound、 upper_bound、 equal_range、binary_search、find_first_of、find_end相关算法,下面对这些算法的源码进行了详细的剖析,并且适当给出应用例子,增加我们对其理解,方便我们使用这些算法。

关注校招求职,微信号:job_campus 4062

STL源码剖析之算法:max & min

template<classT,classCompare>inlineconstT&max(constT&a,constT&b,Comparecomp){returncomp(a,b)?b:a;} template<classT,classCompare>...

weixin_34191845的博客 129

STL源码剖析——STL算法stl_algo.h

本文剖析的STL算法的源码,在剖析源码的同时会给出一些例子,这样加深对其理解,方便我们对这些算法的使用。

关注校招求职,微信号:job_campus 4002

STL源码剖析总结

记录侯捷《STL源码剖析》感悟学习

qq_42579966的博客 1990

iterator转换为reverse_iterator(正向迭代器转为逆向迭代器)

遇到这样一种情形,在set集合中find到某个元素,然后从这个元素,往begin的方向遍历。正常end方向遍历的话,我们可以通过iter != set.end() 作为结束判断。但是往前遍历的话,begin是有数据的,用 iter != set.begin()判断的话,还需要额外进行一次begin元素的操作。 实际上我们是可以将正向迭代器转换为逆向迭代器的。 举个例子。 int main() { std::set<int> si = {1,2,3,4,5,6,7}; ..

veghlreywg的博客 1894

STL源码剖析学习笔记(一)

本文主要是对侯捷《STL源码剖析》学习的知识点总结,以及自己搜集到的资料以及理解,若有任何建议以及意见请联系本人 那么,准备迎接吧

es_tech的博客 3877

18其他算法(algo)——单纯的数据处理

1、单纯的数据处理 有一些算法是只进行单纯的数据移动、线性查找、计数、循环遍历、逐一对元素施行指定运算等操作。这些算法运作逻辑都相对单纯、直观且易懂。 2、adjacent_find 找出第一组满足条件的相邻元素。在版本一中是相邻两元素相等,在版本二中是用户指定一个二元运算,两个操作数分别是相邻的两个元素。 template <class ForwardIterator> ForwardIterator adjacent_find(ForwardIterator first, Forw

Revendell的博客 818

【STL源码剖析】读书笔记

跳过吧在使用迭代器去“撮合”算法和容器时,需要知道容器对象的类型。由此,首先引入了function template参数推导机制,该方法解决了函数形参的推导,但是无法推导出函数的返回值类型。接着有介绍了class的内嵌类型声明,在类(或结构体)中通过typedef T value_type取得参数类型,然后让返回值类型为typename T::value_type获得T的参数类型,但这种方法只在class对象中有效,在原生指针中无法定义内嵌类型。此时,本章最重要的traits特性萃取机就闪亮登场了。

qq_47461884的博客 1354

Unity UI Toolkit避坑指南:从官方Samples到实际项目,这些‘坑’我帮你踩过了

本文分享了Unity UI Toolkit在实际项目中的避坑经验和优化技巧,包括动画系统的高效替代方案、3D世界UI的创新实现方式、USS样式继承的反直觉规则等。通过详细的代码示例和性能优化策略,帮助开发者避免常见陷阱,提升开发效率。

weixin_29535577的博客 343

侯捷——STL源码剖析 笔记

侯捷——STL源码剖析 笔记 1.总览 1.STL六大部件之间的关系 在下图中,我们使用了如下: 1.一个容器vector 2.使用vector时,使用分配器分配内存 3.使用vi.begin(),vi.end()即迭代器,作为算法的参数 4.使用count_if算法 5.使用仿函数less() 6.使用函数适配器来对我们算法的结果进行进一步筛选(not1, bind2nd) 2.复杂度 3.迭代器区间 迭代器是一个左开右闭的区间,也就是说迭代器的end是最后一个元素的下一个元素。 4.容器的结构和

weixin_45067603的博客 1万+

ubunut 系统安装k8s集群

修改配置文件 kube-metrics-server.yaml 添加监控数据采集容器启动参数,启动 tls 证书验证,否则监控容器接口验证不通过,无法采集监控数据。kube-metrics-server.yaml 140行左右添加参数 --kubelet-insecure-tls。服务器添加配置(配置三台阿里云时间同步服务器作为时间源,本机作为时间同步服务器)客户端配置(第一个源选用集群内的 192.168.10.20 )时间同步配置文件参考如下。

weixin_57489252的博客 1330

【STL源码剖析】从源码看 list:从迭代器到算法

本文深入剖析了STL中list容器的实现细节,适合已掌握C++模板和STL基础的开发者学习。文章从六个方面展开:概述list的优劣势;分析节点结构为双向循环链表;探讨迭代器设计与操作重载;揭示循环双向链表的数据结构;讲解构造与内存管理机制;介绍常用接口实现。重点解析了list通过哨兵节点实现"前闭后开"的特性,以及其特有的内存分配方式。文章通过源码分析,展示了STL中list的高效实现技巧,为开发者深入理解STL容器和数据结构提供了宝贵参考。

2401_87944878的博客 7960

ThinkPHP+Layui开发的ERP管理系统

ERP采购生产销售系统,一款基于ThinkPHP+Layui开发的ERP管理系统,帮助中小企业实现ERP管理规范化,此系统能为你解决五大方面的经营问题:1.采购管理 2.销售管理 3.仓库管理 4.资金管理 5.生产管理,适用于:服装鞋帽、化妆品、机械机电、家具装潢、建材行业、快销品、母婴用品、办公用品、汽配汽修、生鲜农贸、手机通讯、数码家电、医药用品、制造业、信息技术服务行业等。提供全部无加密服务端和前端源代码,独立部署,不受限制。

u011092458的博客 788

CIC-IDS2017数据集训练和测试

1、数据集预处理 1.1整合数据并剔除脏数据 如上图所示,整个数据集是分开的,想要训练,必须要整合在一起,同时在数据集中存在Nan和Infiniti脏数据(只有第15列和第16列存在)需要剔除: 具体代码如下: ```python importpandasaspd #按行合并多个Dataframe数据 defmergeData(): monday=writeData("data\MachineLearningCVE\Monday-W...

蓝亚之舟的博客 2万+

侯捷《STL源码剖析》--STL学习笔记

这是我看了《STL源码剖析》之后的一些个人的看法,因为要消化某一个东西,最好的方法就是写下自己的看法和理解。再经过时间的积累,就会慢慢积累到你对真正意义的掌握。这是我的第一个比较正式一点学习笔记,以前也有一些,但都比较零散,其中这段时间对STL比较着迷,也希望得到高手的指点,因为我现在对于ALLOCATOR和adapter还不是很理解,我自己也写过一些仿allocator和adapter,但还不太

spark的专栏 3532

大模型部署指南:SGLang 框架

本文介绍使用 SGLang 框架部署大模型

举世誉之而不加劝,举世非之而不加沮,定乎内外之分,辩乎荣辱之境,斯已矣。 1612

STL源码剖析——STL算法之permutation排列组合

本文讲解的是STL算法中的permutation排列组合算法,根据输入序列,排列出下一个排列组合或前一个排列组合。

关注校招求职,微信号:job_campus 2234

Python爬虫实战:携程旅游平台数据爬取(酒店+机票+景点),破解加密与反爬(附完整代码)

携程的反爬机制再复杂,核心逻辑都是“识别非真实用户的请求”,而爬虫的核心就是“让请求看起来像真实用户的行为”。本文的方案从登录态处理、参数加密破解、动态数据抓取,到反爬应对,都是围绕“模拟真实”展开:用Playwright模拟真实浏览器登录,用住宅代理模拟真实用户IP,用随机延迟模拟真实用户的操作频率。掌握了这个核心思路,无论平台的反爬如何升级,都能找到应对方法。当然,爬虫技术是一把双刃剑,合理使用才能发挥其价值。如果你的爬虫项目中遇到了携程的反爬问题,不妨按照本文的步骤试试,大概率能解决问题。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 2606

vectorCast——Probe point 功能实现故障注入,局部变量打印,断点调试。

选择一个测试用例,选择coverage窗口进行查看。点击edit probe point,如图所示绿色的小圆圈。 选代码中选择需要打断点的地方进行点击。黑色的小圆点都可以选。 点击黑色小圆点,小圆点变绿,表示打断点成功。 此时就可以根据自己的需求在打断点的位置编写一些C语言的命令语句。 点击编译,成功会弹出窗口显示编译成功,失败会在下方报错error,并显示错误的原因。 点击应用保存,选择yes to all就可以了。 点击用例执行就可以看到打断点情况下的执行结果了。

weixin_59334478的博客 2073

STL源码剖析:STL算法

诸如拷贝(copy)、互换(swap)、替换(replace)、填写(fill)、删除(remove)、排列组合(permutation)、分割(partition)、随机重排(random shuffling)、排序(sort)等算法,都属此类。查找(find),匹配(search),计数(count),巡访(for_each),比较,寻找极值(max, min)等算法。lg()计算的是二进制对数的值(即log2),并乘以 2,这是控制分割深度的手段,以防止快速排序出现性能退化的情况。

_ 1520

运放单电源供电和双电源供电的实际应用案例

文章摘要:本文对比分析了运放单电源与双电源供电的典型应用场景及电路设计要点。单电源供电适用于低成本、小体积设备,如便携音箱(5V供电+中点偏置)、工业4-20mA信号转换(12V供电+电压跟随)和物联网传感器(3.3V低功耗设计);双电源供电则适合高精度要求场景,如Hi-Fi音响(±15V对称输出)、医疗设备(±5V微弱信号放大)和精密仪器(±15V宽动态范围)。文末提供常见运放选型对照表,涵盖LM324、TL082等型号的供电参数与核心特性,为不同应用场景提供选型参考。(149字)

qq_37999850的博客 609

STL源码剖析——STL算法之sort排序算法

本文介绍的STL算法中的sort排序算法,SGI STL中的排序算法不是简单的快速排序,而是交叉利用各种排序:堆排序、插入排序和快速排序;这样做的目的是提高效率,针对数据量比较大的采用快速排序,数据量比较小的可以采用堆排序或插入排序。

关注校招求职,微信号:job_campus 2168

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

STL源码剖析——基本算法stl_algobase.h

本文剖析了STL中基本算法的源码,了解其实现机制,方便以后使用STL算法。

关注校招求职,微信号:job_campus 2059

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

上一篇: stl源码剖析 详细学习笔记 算法(1)
下一篇: effective c++ 笔记 (9-12)
boydfd
博客等级 码龄16年 101粉丝 92原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值