185-263 STL

news/2024/11/28 10:50:36/

基本概念:

容器被分为:

序列式容器:每个元素均有固定位置

关联式容器:各元素之间没有严格意义上的物理关系,如二叉树

算法被分为:

质变算法、非质变算法 区别在于运算过程是否会改变区间内元素的内容

迭代器:

提供一种方法,能够依序访问某个容器的各个元素,而无需暴露该容器的内部表示方式。

每个容器都是有自己专属的迭代器

迭代器用法类似指针

迭代器分类:

注意区分const_iterator和const iterator的区别

vector:

遍历实例:

void test(){void myPrint(int);vector<int> a = {10,20,30,40};vector<int>::iterator i;for_each(a.begin(), a.end(), myPrint);
}template<typename T>
void myPrint(T i);//模板函数的声明必须在全局、类、命名空间进行void test2() {STL_Person p1 = { 1,"a" };STL_Person p2 = { 2,"b" };STL_Person p3 = { 3,"c" };STL_Person p4 = { 4,"d" };STL_Person p5 = { 5,"e" };vector<STL_Person> a = { p1,p2,p3,p4,p5 };vector<STL_Person>::iterator i = a.begin();while (i != a.end()) {myPrint(*i);i++;}vector<STL_Person*> b = { &p1,&p2,&p3,&p4,&p5 };vector<STL_Person*>::iterator j = b.begin();while (j != b.end()) {myPrint(**j);j++;}
}
template<typename T>
void myPrint(T i) {cout << "template:" << endl;cout << i << endl;
}
void myPrint(int i) {cout << "int:" << endl;cout << i << endl;
}

注意区分容器的类型为指针时具体使用方式(STL_Person类进行了输出运算符重载)

容器嵌套容器别忘了空格┗|`O′|┛ 嗷~~

头部操作的效率伴随数据量的增大而降低

支持随机访问迭代器

存储结构类似数组,是连续的

赋值方式:使用“=”或assign

改变size大小:resize函数,变短时,多余的部分被删除,变长时,多出的部分被赋予默认值(或可以指定)

互换操作:swap函数,本质是交换,但可以帮助重置capacity,节省内存空间

vector<int>(a).swap(a)

匿名变量拷贝初始化,然后和自己交换,capacity会为拷贝容器设置,最后交换到你要节省空间的容器上,最后在这行执行完后被自动释放。

vector会因为size逼近capacity重新找一段更长的连续空间拷贝,导致原先迭代器指向的位置无效

push_back将元素拷贝加入到容器中,注意当目标元素没有实现拷贝构造时默认为浅拷贝,存在重复删除内存空间的危险

预留空间:reverse函数,改变capacity

string:

赋值、初始化操作自己查文档(利用“=”或assign函数)

拼接操作使用append或“+=”

查找、替换操作

比较操作 使用 “>” “<” “==” 或compare函数

存取操作 使用“[]”或at

deque:

vector访问元素比deque快,push_back速度为O(1),push_front为O(n),所以没有提供后者这个操作

deque支持头部插入删除,该操作的速度比vector快

工作原理:使用中控器维护缓冲区中的内容,中控器记录每一块缓冲区的地址,访问数据速度不如vector的原因在于,所有数据的存放位置不是连续的,而是由多块连续的缓冲区组成

真不戮

deque不存在capacity,只能改变size

stack容器:

先进后出,接口较少,只能返回栈顶元素

对于 stack 对象有一个特例化的全局函数 swap() 可以使用

  • push(const T& obj):可以将对象副本压入栈顶。这是通过调用底层容器的 push_back() 函数完成的。
  • push(T&& obj):以移动对象的方式将对象压入栈顶。这是通过调用底层容器的有右值引用参数的 push_back() 函数完成的。

queue容器:

先进先出,队尾进,队头出,只有队头队尾能被访问,中间元素无法遍历

list容器:

使用链表结构,所以插入删除方便,但是遍历访问慢,多占用了几份指针的空间

STL的链表为双向链表

仅支持前移和后移,不支持随机访问(走多步)

动态存储分配,不会造成内存溢出和浪费

不支持“[]”、at方式访问元素

类似的,不支持迭代器 +1、+2操作,不支持标准sort算法(涉及随机访问)

set和multiset容器:

关联式容器,使用二叉树实现,不支持随机访问迭代器

关联容器需要一个排序基准

只有insert的插入方式,并自动排序,不会插入重复值,multiset可以插入重复值

insert返回pair<iterator,bool>类型

erase函数具有remove作用的重载函数

使用find和count查找和计数指定元素是否存在以及统计指定元素个数

find返回的是迭代器,所以没有找到时返回的是 set.end()

利用仿函数帮助容器处理元素的排序顺序,具体初始化方式为:set<type,func>

pair对组:

创建方式:

    pair<int, int> p = { 1,5 };pair<int, int> p1(1, 5);pair<int, int> p3 = pair<int, int>(1, 5);pair<int, int> p2 = make_pair(1, 5);

map和multimap容器:

由pair组成,分别为key和value,map根据键值进行排序,不支持随机访问迭代器

插入必须使用pair,删除根据key(键值)来删

map不允许有相同键值元素在容器中,multimap可以

不建议使用“[]”运算符重载创建,因为该语句会在该键值不存在时自动创建

用法实例

	map<string, int> m;m.insert(make_pair("abc", 3));cout << m["abc"] << endl;

emplace:

emplace操作是C++11新特性,新引入的的三个成员emplace_front、emplace 和 emplace_back,这些操作构造而不是拷贝元素到容器中,这些操作分别对应push_front、insert 和push_back,允许我们将元素放在容器头部、一个指定的位置和容器尾部

函数对象(仿函数):

针不戮

一个函数对象是封装在类中, 从而看起来更像是一个对象。 这个类只有一个成员函数, 即重载了() (括号)的运算符。 它没有任何数据。 该类被模板化了, 从而可以应付多种数据类型。

仿函数就是在类中重载“()”运算符

比起普通函数,函数对象可以拥有状态(函数可以写该类的成员,达到记忆效果)

用例:

class Greater {
public:int value;bool operator() (int val) {return val > value;}Greater(int val) :value(val) {}
};
template<typename T>
class between {
public:T max;T min;between(T a, T b):max(b),min(a){}bool operator() (T val) {return less<T>()(val,max) && greater<T>()(val,min);}
};
void test01() {//copy算法void STL_Print(int&);vector<int> a = { 6,5,5,4,3,2,1 };vector<int> b;b.resize(a.size());copy(a.begin(), a.end(), b.begin());for_each(a.begin(), a.end(), STL_Print);
}
void test02() {//replace、replace_if算法void STL_Print(int&);vector<int> a = { 6,5,5,4,3,2,1 };replace(a.begin(), a.end(), 1, 2);for_each(a.begin(), a.end(), STL_Print);cout << endl;replace_if(a.begin(), a.end(), bind(greater<int>(), placeholders::_1, 5), 100);for_each(a.begin(), a.end(), STL_Print);cout << endl;replace_if(a.begin(), a.end(), bind(between<int>(4,100),placeholders::_1), 100);for_each(a.begin(), a.end(), STL_Print);cout << endl;Greater greater(101);replace_if(a.begin(), a.end(), greater, 100);for_each(a.begin(), a.end(), STL_Print);
}
void test() {test02();
}
void STL_Print(int &a) {a++;cout << a << ",";
}
//test02输出
//7, 6, 6, 5, 4, 3, 3,
//101, 101, 101, 6, 5, 4, 4,
//102, 102, 102, 101, 101, 5, 5,
//101, 101, 101, 102, 102, 6, 6,

谓词:

返回bool类型的仿函数称为谓词,根据参数的多少被分为一元谓词和二元谓词

例如:一元谓词配合find_if函数,二元谓词配合sort函数

内建函数:

functional库

被分为算术仿函数(加减乘除取余...)、关系仿函数(大于小于等于...)、逻辑仿函数(与或非,应用较少)

transform操作:

algorithm库

使用transform搬运时需注意目标容器的容量(不会动态开辟更大空间)

查找操作:

find操作查找特定元素

find_if使用一元谓词/普通函数提供筛选条件

adjacent_find查找相邻重复元素

binary_search要求有序序列(通过二元谓词/普通函数告诉容器的排序方式,否则默认升序排列)

void test01() {//adjacent find 查找相邻重复元素 binary_search二分查找bool less(int, int);greater<int> n;vector<int> a = { 6,5,5,4,3,2,1 };auto i = adjacent_find(a.begin(), a.end());cout << *i << endl;cout << binary_search(a.begin(), a.end(), 3, less) << endl;
}
bool less(int a, int b) {return a > b;
}
void test() {test01();
}

count统计容器中相等的元素个数(自定义类型使用运算符重载),count_if同find和find_if的区别

排序操作:algorithm库

sort排序:

支持随机迭代器的容器均支持sort排序,否则使用容器的成员sort函数

可以提供仿函数/普通函数/内建函数,指定结果为true的时候是想要的排序顺序

random_shuffle洗牌:

配合srand生成种子成为真随机

merge合并:

要求被合并的两个序列都是有序的,进行归并

需要指向被合并容器和目标容器的迭代器来规定合并范围和合并起始点

新容器有时需要事先resize(reserve不行)

reverse反转:

没啥

常用拷贝和替换算法:algorithm库

copy算法:

提供被copy的容器的起始位置和最终位置,以及目标容器的位置

replace、replace_if算法:

将区间内所有 指定/符合条件 的旧值替换为指定新值

swap算法:

必须是同类容器

常用算术生成算法:numeric库

accumulate:

求累加值,需要容器的范围及起始值

fill:

容器范围内元素全部替换为指定值

常用集合算法:algorithm库必须是有序序列(也可以通过仿函数、普通函数告诉容器的排序方法)

set_intersection:将两个容器的交集放在目标容器中

set_union:并集

set_difference:差集

示例:

void test03() {//set_intersection求交集、并集、差集void STL_Print(const int&);vector<int> a = { 6,5,4,3,1 };vector<int> b = { 6,5,4,2 };vector<int> c(a.size()+b.size(),0);auto pos = set_intersection(a.begin(), a.end(), b.begin(), b.end(), c.begin(), [](int a, int b) ->bool {return a > b; });for_each(c.begin(), pos, STL_Print);cout << endl;pos = set_union(a.begin(), a.end(), b.begin(), b.end(), c.begin(), [](int a, int b) ->bool {return a > b; });for_each(c.begin(), pos, STL_Print);cout << endl;pos = set_difference(a.begin(), a.end(), b.begin(), b.end(), c.begin(), [](int a, int b) ->bool {return a > b; });for_each(c.begin(), pos, STL_Print);
}
//6, 5, 4,
//6, 5, 4, 3, 2, 1,
//3, 1,
void test() {test03();
}
void STL_Print(const int &a) {cout << a << ",";
}
void STL_Print(int& a) {a++;cout << a << ",";
}


http://www.ppmy.cn/news/346428.html

相关文章

用stm32f103c8t6点亮0.96寸oled屏(附带百度云例程)

oled的技术文档中的例程好像时用keil4开发的&#xff0c;keil5打开时有问题&#xff0c;因此用自己建的c8t6工程做了移植&#xff0c;亲测有效。 首先挂出链接 链接&#xff1a;https://pan.baidu.com/s/19H5pTt2JeQYA_LBdDxZRag 提取码&#xff1a;1234 工程的简单说明 端…

STM32学习笔记-L298N驱动模块-电机

新手上路&#xff0c;十几天的学习感觉弯路走了不少&#xff0c;所以打算把学习的知识记录下来&#xff0c;和大家分享&#xff0c;不要嫌弃我&#xff0c;我从非常新手的角度来写。 1、STM32F103RCT6 我也是第一次学习单片机&#xff0c;选择了正点原子家的迷你版&#xff0…

STM32F103C8T6 0.42寸的OLED屏幕IIC例程

初始化部分 void OLED_Init(void) {GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能A端口时钟GPIO_InitStructure.GPIO_Pin GPIO_Pin_0|GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_OD; //推挽输出G…

HW-95 L298N电机驱动板模块的使用

int input1 5; // 定义uno的pin 5 向 input1 输出 int input2 6; // 定义uno的pin 6 向 input2 输出 int input3 9; // 定义uno的pin 9 向 input3 输出 int input4 10; // 定义uno的pin 10 向 input4 输出 void setup() { // Serial.begin (9600); //初始化各IO,模…

STM32驱动W25Q128

1、W25Q128 是华邦公司推出的一款 SPI 接口的 NOR Flash 芯片&#xff0c;其存储空间为 128Mbit&#xff0c;相当于 16M 字节。 W25Q128 可以支持 SPI 的模式 0 和模式 3&#xff0c;也就是 CPOL0/CPHA0 和CPOL1/CPHA1 这两种模式。 2、写入数据时&#xff0c;需要注意以下两个…

【C++】 STL(上)STL简述、STL容器

文章目录 简述STL容器list链表vector向量deque双端队列map映射表set集合hash_map哈希表 简述 STL是“Standard Template Library”的缩写&#xff0c;中文译为“标准模板库”。STL是C标准库的一部分&#xff0c;位与各个C的头文件中&#xff0c;即他并非以二进制代码的形式提供…

L298N模块的连接与使用(stm32驱动与51驱动)

一、L298N的一些基本参数 使用方法&#xff1a; 输出A&#xff1a; 通道A输出 &#xff0c;连接电机 输出B: 通道B输出 &#xff0c;连接电机 12V供电&#xff1a; 主电源正极输入 供电GND: 主电源正负极极输入 5V输出&#xff1a; 5v电压输出端&#xff0c;可用…

L226WTQ 参数

分辨率&#xff1a;1680x1050 水平刷新率&#xff1a;30-83KHz 垂直刷新率&#xff1a;56-75Hz