C++新经典 | C++ 查漏补缺(STL标准模板库)

news2024/11/17 5:47:46

目录

一、STL总述

1.容器

(1)顺序容器

(2)关联容器

(3)无序容器

(4)常用容器

(4.1)array 数组

(4.2)vector

(4.3)deque 队列

(4.4)stack 栈

(4.5)queue 队列

(4.6)list 双向链表

(4.7)forward_list 单向链表

(4.8)map和set

(4.9)unordered_map与unordered_set等

(4.10)vector和list这两个容器的区别

2.分配器

3.迭代器        

(1)迭代器的分类

4.算法

(1)常用算法

(1.1)for_each

(1.2)find

(1.3)find_if

(1.4)sort

5.函数对象

(1)自定义函数对象

(2)标准库中定义的函数对象


一、STL总述

  1. C++标准库:英文名字是C++Standard Library。
  2. 标准模板库:英文名字是StandardTemplateLibrary(STL)。包含在C++标准库之中,作为C++标准库的一个重要组成部分或者说是C++标准库的核心,深深影响着标准库。
  3. C++标准库中包含很多的头文件,其中和STL相关的头文件有几十上百个(不同的STL版本的文件数目不同)。在使用STL的时候,也需要把这些头文件包含到自己的项目中来,现代版本标准库中的头文件名字,已经把.h扩展名去掉,变成了没有扩展名的头文件。还有一些C语言的标准头文件,以往的如#include<stdlib.h>,在新版本下推荐写成#include<cstdlib>。注意,这种写法是文件名前面多了个字母c,文件扩展名.h也被去掉了。当然,老版本的写法#include<stdlib.h>仍然能用(因为这些.h文件依然存在)。
  4. STL的组成部分:容器、迭代器、算法(可以理解成STL提供的一些函数,用来实现一些功能,例如查找用到search,排序用到sort,复制用到copy)、分配器(用于分配内存)、其他(包括适配器、仿函数/函数对象等)。

1.容器

        STL中的容器可以分成三类:顺序容器、关联容器、无序容器。

(1)顺序容器

        顺序容器(Sequence Containers)的意思就是放进去的时候把这个元素(放进容器中的数据称为容器中的元素)排在哪里,它就在哪里,例如把它排在最前面,那它就会一直在最前面待着,这就是顺序容器。如array、vector、deque、list、forward_list等容器都是顺序容器。

(2)关联容器

        这种容器,它的每一个元素都是一个键值(key/value)对,用这个键来找这个值就特别迅速和方便。

        关联容器的内部一般是使用一种称为“树”的数据结构实现数据的存储。刚刚谈到顺序容器时笔者说过,顺序容器是那种放进去的时候把这个元素排在哪里,它就在哪里。而关联容器则不同,把一个元素放到关联容器里去的时候,该关联容器会根据一些规则,如根据key,把这个元素自动放到某个位置。

        换句话说,程序员不能控制元素插入的位置,只能控制插入的内容。set、map、multiset、multimap等都属于关联容器(Associative Containers)。

(3)无序容器

        这种容器是C++11里推出的容器,按照官方的说法,这种容器里面的元素位置不重要,唯一重要的是这个元素是否在这个集合内。一般插入这种元素的时候也不需要给要插入的元素安排位置,这种容器也是会自动给元素安排位置。所以,根据这种容器的特点,无序容器(Unordered Containers)应该属于一种关联容器。

        随着往这个容器中增加的元素数量的增多,很可能某个元素在容器中的位置会发生改变,这是由该容器内部的算法决定的。因此“无序容器”这种名字还是挺贴切的。无序容器内部一般是用哈希表这种数据结构来实现的。例如,unordered_set、unordered_multiset、unordered_map、unordered_multimap等都是无序容器。


        C++标准并没有规定任何容器必须使用任何特定的实现手段。但一般来讲,都有规律可循,例如map用的是树这种数据结构存储数据,hash_开头的容器一般用的是哈希表这种数据结构存储数据。


(4)常用容器

(4.1)array 数组

        array是一个顺序容器,其实是一个数组,所以它的空间是连续的,大小是固定的,刚开始时申请多大,就是多大,不能增加它的大小。

(4.2)vector

        vector的空间是连续的,这个空间一增长,就要找一块新的足以容纳下当前所有元素的内存,把所有元素搬到新内存去,这一搬就很容易想到,老的容器中元素要析构,这些搬来的元素都要重新执行构造函数来构造。这显然非常影响程序执行效率。

        容器里面有多少个元素可以用size来查看,而容器的空间可以用capacity来查看。capacity的结果一定不会小于size,也就是说容器中空间的数量一定不会比元素数量少。

        当vector容器中删除一个元素时,会导致执行一次析构函数,然后所有后续元素的内存往前动(至少从表面上看元素对象是往前移动了),但并没有执行这些移动了的对象的任何构造和析构函数,这说明编译器内部有自己的处理,这个处理就很好。

        向vector容器中间插入元素会导致后续的一些元素都被析构和重新构造,从中间插入元素代价都很大。所以,如果事先不知道有多少个元素要往vector里插入,需要的时候就往里插入一个,那么显然vector容器的运行效率应该不会高——频繁大量地构造、析构、寻找新的整块内存,这都是很让开发者忌讳的。但是,如果事先知道整个程序运行中这个vector容器里最多也不会超过多少个元素,例如程序员知道最多也不会超过10个元素,那就让capacity事先等于10(在容器中预留10个空间),这样往容器中插入元素时,只要不超过10个,那么就不需要频繁地构造和析构元素对象。换句话说,就不需要寻找新的整块内存进行元素搬迁了(所以,利用好capacity也能够提升vector容器的效率。)。

(4.3)deque 队列

        deque这种顺序容器是一个双端队列(双向开口),deque是double-ended queue的缩写。该队列相当于一个动态数组,因为它是双端的,所以无论在头部还是在尾部插入和删除数据都会很快,但是若要在中间插入数据,因为要移动其他元素,效率就会比较低。

        deque其实是一个分段数组。当插入元素多的时候,它就会把元素分到多个段中去,当然,每一段的内存是连续的(所以只能说内存是分段连续)。

(4.4)stack 栈

        stack和vector有点类似,但请注意,vector还支持insert、erase,也就是说,vector支持从中间插入和删除元素的操作。但是stack只支持往栈顶放入元素和从栈顶取出元素(删除元素),因为stack这种容器设计的初衷就要求具备这种特性。

        deque是包含stack功能的。

(4.5)queue 队列

        deque是双端队列,但queue是普通队列(简称队列)。队列是一种比较基本的数据结构,其特点是先进先出。也就是说,元素从一端进入,从另一端取出(删除元素),queue容器设计的初衷就要求具备这种特性。

        deque也是包含queue功能的。

(4.6)list 双向链表

        list这种顺序容器是一个双向链表。各个元素之间不需要紧挨在一起,只需要用指针通过指向把元素关联起来即可。

        list双向链表的特点:查找元素要沿着链来找,所以查找的效率并不突出,但因为它是一个双向链,所以在任意位置插入和删除元素都非常迅速——几个元素中的指针一改变指向就可以了。

(4.7)forward_list 单向链表

        这是C++11新增加的顺序容器,是一个单向链表。forward_list比list少了一个方向的链(指针),官方称它为受限的list。少了一个方向的指针,会造成一定的访问不便,但是少了一个方向的指针后,一个容器中的元素就能节省下4字节的内存(在x86平台下)。容器中的元素若是很多,则省下的内存也很可观。

        很多容器都有push_back成员函数,但是forward_list容器只有push_front,这说明这个容器最适合的是往前头插入元素。

(4.8)map和set

        map和set都是关联容器。map和set这类容器内部的实现多为红黑树,红黑树这种数据结构本身内部有一套很好的保存数据的机制。向这种容器中保存数据的时候不需要指定数据的位置,这种容器会自动给加入的元素根据内部算法安排位置。

        插入元素的时候,因为这类容器要给插入的元素找一个合适的位置,所以插入的速度可能会慢一些,但是,得到的好处是查找的时候快,所以对于需要快速找到元素的应用场景,重点考虑使用map、set这类容器。

        map容器的每个元素(树节点)都是一个键值对(key/value)。这种容器通过key查找value的速度非常快,但不允许在一个map容器中出现两个相同的key,所以,如果key有可能重复,请使用multimap容器。

        set容器中的元素没有key和value之分,每个元素就是一个value。元素保存到容器中后,容器会自动把这个元素放到一个位置,每个元素的值不允许重复,重复的元素插入进去也没有效果。如果想插入重复的元素,请使用multiset容器。

(4.9)unordered_map与unordered_set等

        以往的诸如hash_set、hash_map、hash_multiset、hash_multimap,这些老的容器也能使用,但并不推荐使用了,新版本的容器一般都是以unordered_开头了。以unordered_开头的容器属于无序容器(关联容器的一种),无序容器内部一般是使用哈希表(散列表)来实现的。

        unordered_map和unordered_multimap每个元素同样是一个键值对,unordered_map中保存的键是不允许重复的,而unordered_multimap中保存的键可以重复。

        unordered_set和unordered_multiset的每个元素都是一个值,unordered_set中保存的值不允许重复,而unordered_multiset中保存的值可以重复。

(4.10)vector和list这两个容器的区别
  • vector类似于数组,它的内存空间是连续的,list是双向链表,内存空间并不连续。
  • vector插入、删除元素效率比较低,但list插入、删除元素效率就非常高。
  • vector当内存不够时,会重新找一块内存,对原来内存中的元素做析构,在新找的内存重新建立这些对象(容器中的元素)。
  • vector能进行高效的随机存取(跳转到某个指定的位置存取),而list做不到这一点。例如,要访问第5个元素,vector因为内存是连续的,所以极其迅速,它一下就能定位到第5个元素(一个指针跳跃一定数量的字节就可以到达指定位置)。反观list,要找到第5个元素,得顺着这个链逐个地找下去,一直找到第5个。所以说vector随机存取非常快,而list随机存取比较慢。

2.分配器

        跟容器紧密关联在一起使用的是分配器,只是在编写代码时,一般都采用系统默认的分配器,不需要自己去指定分配器。

    std::list<int> list;
    std::list<int, std::allocator<int>> list;

        分配器的引入主要扮演内存池的角色,大量减少对malloc的调用以减少对内存分配的浪费。(分配器就是一次分配一大块内存,然后从这一大块内存中给程序员每次分配一小块来使用,用链表把这些内存块管理起来。这种内存池的内存分配机制有效地减少了调用malloc的次数,也就等于减少了内存的浪费,同时还一定程度上提高了程序运行效率。)

#include <list>
void TestSTL()
{
    //分配器
    std::list<int> list;//默认的分配器std::allocator<int>,并没有实现内存池

    list.push_back(1);
    list.push_back(2);
    list.push_back(3);

    //迭代器
    for (std::list<int>::iterator iter = list.begin(); iter != list.end(); iter++)
    {
        std::cout << *iter << std::endl;
    }
}

        系统默认为程序员提供了allocator这个默认的分配器,这是一个类模板,是标准库里写好的,直接提供给程序员使用的。当然,程序员也可以写一个自己的分配器用在容器中,这是可行的。默认的allocator到底怎样实现的,除非读它的源码,否则并不清楚它是否是通过一个内存池来实现内存分配的,也可能它根本就没实现什么内存池,而是最终简单地调用底层的malloc来分配内存,这都是有可能的。

        分配器是一个类模板,带着一个类型模板参数。C++标准库中的容器,如std::vector、std::list等,默认使用std::allocator作为其分配器。但是用户可以提供自定义的分配器来改变容器如何获取和释放内存。一个典型的分配器需要定义以下类型和函数:

  • value_type: 分配值的类型。
  • allocate(): 分配未初始化内存。
  • deallocate(): 释放先前由 allocate 分配的内存。
  • construct(): 在给定位置上构造元素。
  • destroy(): 销毁在给定位置上已经构造好的元素。

3.迭代器        

        迭代器是一个“可遍历STL容器全部或部分元素”的对象(为了方便理解,可以把迭代器理解为:行为类似于指针的对象)。迭代器用来表现容器中的某一个位置,迭代器是由容器来提供的。也就是说,一般来讲,是容器里面定义着迭代器的具体类型细节。

        既然迭代器可以理解成行为类似于指针的对象,那么对于指针,可以用如*p来读取指针所指向的内容,所以对于迭代器,用如*iter一般也能读取到迭代器所指向的内容。

(1)迭代器的分类

        迭代器与一个指针一样,到处跳,表示一个位置。分类也是根据它跳跃的能力来分的,每个分类都对应着一个struct结构。迭代器主要分为以下5类,这些结构是有继承关系的。

  • 输出型迭代器(Output iterator)
  • 输入型迭代器(Input iterator)
  • 前向迭代器(Forward iterator)
  • 双向迭代器(Bidirectional iterator)
  • 随机访问迭代器(Random-access iterator)
迭代器分类相关结构继承关系图(最上面辈分最高,最下面辈分最低)

        所谓随机读取,指的是跳过一定个数的元素,如当前位置在第1个元素这里,可以立即跳过3个元素直达第4个元素。随机访问迭代器看起来最灵活,因为随机访问迭代器支持的操作最多,如一次可以跳跃多个元素等。其所支持的容器array、vector的元素内存都是连续的,所以要跳到如第5个元素上,非常方便,做个加法运算,就立即能跳过去。deque这个双端队列容器虽然支持的迭代器也是随机访问迭代器,但这个容器是分段连续的,也就是说内存中它并不是真连续,虽然不是真连续,但它的迭代器仍旧是随机访问,也就是一次可以跳跃多个元素,这个设计还是挺精妙的。总之,支持随机访问迭代器的容器多数都是内存连续的。

        也可以看到vector和list容器的区别:这两个容器所支持的迭代器类型不同,vector容器支持的是随机访问迭代器,list容器支持的是双向迭代器,没有随机访问迭代器支持这么多的迭代器操作。所以,vector容器和list容器的一个主要区别就是:vector能进行高效的随机存取,而list做不到这一点。

4.算法

        算法可以理解成函数。更准确的说法是:算法理解为函数模板。STL中提供了很多算法,如查找、排序等,有数十上百个之多,而且数量还在不断增加中。

        每个容器都带着许多适合该容器自身进行各种操作的成员函数,而算法不同于这些成员函数,可以把算法理解成全局函数或者全局函数模板(不针对某一个容器,但对部分或者大部分容器都适用)。既然算法是函数模板,它就有参数,也就是形参,那么传递进来的这些形参的类型一般前两个形参都是迭代器类型,用来表示某个容器中元素的一个区间,这个区间还得注意一下。

        这种前闭后开区间的好处一般认为有两条:

  • 算法只要判断迭代器等于后面这个开区间,那就表示迭代结束。
  • 如果第一个形参等于第二个形参,那这就表示是一个空区间。
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> v = {4, 2, 5, 3, 1};
    std::sort(v.begin(), v.end());
    
    // 现在v包含{1, 2, 3, 4, 5}
    
    return 0;
}

        算法是一种搭配迭代器来使用的全局函数(或全局函数模板)。这些算法和具体容器没有什么关系,只跟迭代器有关,大部分容器都有迭代器。也就是说,这些算法对于大部分容器都是适合的,不需要针对某种容器专门定制。

        当然,算法作为单独的一个函数(函数模板)来实现,也是违背了面向对象程序设计所讲究的封装性(把成员变量、成员函数包装到一起)的特点,这一点是比较遗憾的。

(1)常用算法

(1.1)for_each

        for_each看起来像一个语句,实际是一个算法。

        for_each的第一个和第二个形参都是迭代器,表示一段范围(或者说表示某个容器中的一段元素),for_each的第三个参数实际上是一个可调用对象。

(1.2)find

        find用于寻找某个特定值。

        有些容器自己有同名的成员函数(包括但不限于这里讲到的find函数),优先使用同名的成员函数(但同名的成员函数不像算法,一般不需要传递进去迭代器作为前两个参数),如果没有同名的成员函数,才考虑用全局的算法。

(1.3)find_if

        find_if的调用返回一个迭代器(如:vector<int>::iterator),指向第一个满足条件的元素,如果这样的元素不存在,则这个迭代器会指向vector.end()。这个算法与find类似,只是find第三个参数是一个数字,而这里的find_if的第三个参数是一个可调用对象(lambda表达式),这个可调用对象里有一个规则——找第一个满足该规则的元素。

(1.4)sort

        sort用于排序的目的。

        sort算法应用于list容器时会报错,说明这个算法对list容器不适用。因为sort算法适用于随机访问迭代器而不适用于双向迭代器。

        list容器有自己的sort成员函数,当然就使用list容器自身提供的sort成员函数了。

5.函数对象

        sort的第三个参数是一个函数对象(functionobjects)或者叫仿函数(functors),用来指定一个排序的规则。仿函数其实就是函数对象,只不过仿函数这个称呼比较老,新称呼是函数对象。

        这种函数对象在STL里面一般都是用来跟算法配合使用以实现一些特定的功能。换句话来说,这些函数对象主要用来服务于算法。

函数对象的各种形式

(1)自定义函数对象

bool myCompare(int a, int b) {
    return (a > b);
}

int main() {
    std::vector<int> v = {1, 5, 2, 4, 3};
    std::sort(v.begin(), v.end(), myCompare);
}

(2)标准库中定义的函数对象

        除了自己写的函数对象,标准库中也提供了许多可以现成拿来使用的函数对象。函数对象分类:算术运算类、关系运算类、逻辑运算类、位运算类。

#include <functional>
算术运算类
关系运算类
逻辑运算类
位运算类
 std::cout << std::plus<int>()(3, 5) << std::endl;
  • plus <int>是一个实例化了的类。
  • 类名后面加一个圆括号也就是“plus<int>()”代表生成一个类plus<int>的临时对象(因为plus中重载了operator(),所以这个临时对象是一个可调用对象)。
  • 为了调用这个可调用对象,在临时对象后面,增加圆括号(),之后plus类模板的operator()中有什么参数,这个圆括号中就要有什么参数。(plus类模板的operator()中需要两个参数。)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1115917.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软件功能测试的6种方法

对于测试人员而言&#xff0c;软件产品每个按钮的功能是否准确&#xff0c;链接是否能正常跳转&#xff0c;搜索时会不会出现页面错误&#xff0c;验证并减少这些软件使用过程中可能出现的各种小问题都是功能测试的内容。而对于用户而言&#xff0c;功能能否正常执行都是非常直…

Visual Components软件有哪些用途 衡祖仿真

Visual Components是一款用于制造业虚拟仿真的软件&#xff0c;主要用于工业自动化和制造领域。我们一起来看一下该软件有哪些功能吧&#xff01; 1、工厂仿真 Visual Components可以建立虚拟的工厂环境&#xff0c;模拟和优化生产流程。用户可以创建工厂布局、定义设备和机器人…

【试题031】C语言关系运算符和逻辑非例题

1.题目&#xff1a; 设int p;&#xff0c;与if(p0)等价的是 () A if(p) B if(!p) if(p1) Dif(p!0) 2.分析&#xff1a; [ ] if中的条件是p0为真&#xff0c;也就是说p0[ ] 那么&#xff01;p1,逻辑非就是将结果取反的操作[ ] p0也就是p≠1 3.截图&#xff1a;

KT142C语音芯片直接焊到我的板子上面,插上usb,但是出不来虚拟U盘怎么办

KT142C的芯片&#xff0c;我直接焊到我的板子上面&#xff0c;插上usb&#xff0c;但是出不来虚拟U盘怎么办&#xff1f; 1、这个问题&#xff0c;其实最好的解决方案&#xff0c;就是对比我们的测试板&#xff0c;因为出现这种情况&#xff0c;不好找原因 2、但是有测试板的话…

【Arduino32】PWM控制直流电机速度

硬件准备 震动传感器&#xff1a;1个 红黄绿LED灯&#xff1a;各一个 旋钮电位器&#xff1a;1个 直流电机&#xff1a;1个 1K电阻&#xff1a;1个 220欧电阻&#xff1a;3个 杜邦线&#xff1a;若干 硬件连线 软件程序 const int analogInPin A0;//PWM输入引脚 const…

AWS SAP-C02教程8-大数据和机器学习

接下来是一个组跟数据和机器学习有关的内容,这部分在SAP-C02考试中目前占比可能不多且不是很深入,但是随着AI的趋势,这部分内容将会越来越重要,但是经常会出现在考题的选项中,因此了解其基本功能和在解决方案中的应用也是非常重要的。 目录 1 大数据1.1 Kinesis家族1.1.1…

JMeter添加插件

一、前言 ​ 在我们的工作中&#xff0c;我们可以利用一些插件来帮助我们更好的进行性能测试。今天我们来介绍下Jmeter怎么添加插件&#xff1f; 二、插件管理器 ​ 首先我们需要下载插件管理器jar包 下载地址&#xff1a;Install :: JMeter-Plugins.org 然后我们将下载下来…

Docker-镜像的备份迁移及私有仓库的搭建

一、Docker-备份与迁移 A服务器系统配置 B服务器系统配置 1.用命令将容器保存为镜像。 案例&#xff0c;将A服务器的Docker容器迁移到另外一台服务器B&#xff0c;A服务器的容器配置过对应的文件&#xff0c;不想在B服务器重新搭建&#xff0c;可以使用该案例。 docker c…

vue 组件封装 综合案例1

vue 组件封装 综合案例 **创建 工程&#xff1a; H:\java_work\java_springboot\vue_study ctrl按住不放 右键 悬着 powershell H:\java_work\java_springboot\js_study\Vue2_3入门到实战-配套资料\01-随堂代码素材\day05\准备代码\11-综合案例-商品列表 vue --version vue c…

2023年中国游戏机设备分类、销量及市场规模分析[图]

游戏机设备行业是指生产和销售游戏机设备的行业&#xff0c;包括游戏机硬件、游戏软件、游戏周边设备等。随着科技的进步和游戏市场的不断扩大&#xff0c;游戏机设备行业也在不断发展和和创新。 游戏机设备分类 资料来源&#xff1a;共研产业咨询&#xff08;共研网&#xff…

关于setInteval定时器在不同浏览器下表现差异

背景: 项目下用到websocket, 中间使用了setInterval 定时向服务端发送心跳包, 5s/次, 观察正常, 就将浏览器最小化后, 经过了两天, 周一过来查看, 咋才 5000次; 问题分析: 遇到这种简单的问题当然是请教一下GPT 来的最快最实际, 不出所料, 马上得到证实; chrome 88 版本之…

CentOS7.9离线安装 Nginx

1. 下载Nginx安装包 下载地址&#xff1a;http://nginx.org/download/nginx-1.20.1.tar.gzhttp://nginx.org/download/nginx-1.20.1.tar.gz 2. 找到Nginx安装时需要的依赖包 我这里是下载了CentOS7.9的安装镜像 阿里下载地址&#xff1a;centos-7.9.2009-isos-x86_64安装包…

大白话聊AVL树

文章目录 前言AVL树的平衡性不平衡的几种情况AVL树恢复平衡LL恢复平衡RR恢复平衡LR恢复平衡RL恢复平衡 总结 前言 上文对常见的数据结构进行了简单介绍&#xff0c;包括它们的定义、性质和特点。本文将对AVL树展开介绍&#xff0c;通过对AVL树的插入、删除、查找以及旋转操作全…

CleanMyMac X4.14.4最新免费版本功能介绍

最新版CleanMyMac X 让您的Mac焕然一新&#xff0c;时刻保持安全&#xff01;CleanMyMac X是一款专业的Mac清理软件&#xff0c;可智能清理mac磁盘垃圾和多余语言安装包&#xff0c;快速释放电脑内存&#xff0c;轻松管理和升级Mac上的应用。同时CleanMyMac X可以强力卸载恶意软…

力扣第332题 重新安排行程 c++ 难

题目 332. 重新安排行程 困难 相关标签 深度优先搜索 图 欧回路 给你一份航线列表 tickets &#xff0c;其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。 所有这些机票都属于一个从 JFK&#xff08;肯尼迪国际机…

通达信神奇九转指标原理及选股公式,无未来函数,数字不消失

神奇九转指标的原理源自技术分析师汤姆迪马克(Tom Demark)发明的TD序列&#xff0c;用于识别趋势衰竭和价格反转的时间。神奇九转指标是一种震荡指标&#xff0c;目的在于解决一些技术分析指标在趋势行情中有利可图&#xff0c;但在震荡行情中表现很差的问题。 一、神奇九转指标…

算法通关村第19关【白银】| 动态规划高频问题

1.零钱兑换 思路&#xff1a; 确定dp&#xff1a;这里是最少硬币的个数&#xff0c;不是种类 确定递推公式&#xff1a;dp[j] Math.min(dp[j],dp[j-coins[i]]1),不要当前硬币dp[j]还是保持以前的组合方法,要当前硬币dp[j-coins[i]]1 确定初始化&#xff1a;dp[0]0,其他的都…

NFT Insider112:The Sandbox聘请Apple高管担任其首席内容官,YGG 将在菲律宾举办Web3游戏峰会

引言&#xff1a;NFT Insider由NFT收藏组织WHALE Members、BeepCrypto联合出品&#xff0c;浓缩每周NFT新闻&#xff0c;为大家带来关于NFT最全面、最新鲜、最有价值的讯息。每期周报将从NFT市场数据&#xff0c;艺术新闻类&#xff0c;游戏新闻类&#xff0c;虚拟世界类&#…

华为eNSP配置专题-浮动路由及BFD的配置

文章目录 华为eNSP配置专题-浮动路由及BFD的配置0、参考文档1、前置环境1.1、宿主机1.2、eNSP模拟器 2、基本环境搭建2.1、基本终端构成和连接2.2、基本终端配置 3、浮动路由配置3.1、浮动路由的基本配置3.2、浮动路由的负载均衡问题3.3、浮动路由的优先级调整 4、BFD的配置4.1…

YOLOv8改进实战 | 更换主干网络Backbone(四)之轻量化模型MobileNetV3

前言 轻量化网络设计是一种针对移动设备等资源受限环境的深度学习模型设计方法。下面是一些常见的轻量化网络设计方法: 网络剪枝:移除神经网络中冗余的连接和参数,以达到模型压缩和加速的目的。分组卷积:将卷积操作分解为若干个较小的卷积操作,并将它们分别作用于输入的不…