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

STL学习

STL基础

STL从广义上分为:容器,算法,迭代器
容器和算法之间通过迭代器进行无缝连接

STL 的六大组件

STL六大组件分别是:容器、算法、迭代器、仿函数、适配器、空间适配器

容器:各种数据结构,如vector,list、deque、set、map等用来存放数据
算法:各种常用的算法,如sort、find等
迭代器:扮演了容器与算法之间的胶合剂
仿函数:行为类似函数,可以作为算法的某一种策略
适配器:一种用来修饰容器或者仿函数或迭代器接口的东西
空间适配器:负责空间的配置与管理

容器分为序列式容器和关联式容器

序列式容器:强调值的排序,序列式容器中的每一个元素均有固定的位置
关联式容器:二叉树结构,个元素之间没有严格的物理上的顺序关系

算法:解决问题的方法,有限的步骤,解决逻辑或数学上的问题
算法分为质变算法和非质变算法

质变算法:指质变过程中会更改区间内的元素的内容
非质变算法:在运算过程中不会更改区间内的元素内容

迭代器:提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方法
每个容器都有自己的专属迭代器
迭代器的使用类似于指针

vector

vector初始化

int main() {// v1 是一个元素类型为 int 的空 vectorvector<int> v1;// 使用 v1 中所有元素初始化 v2vector<int> v2(v1);vector<int> v2 = v1;// v3 中包含了 3 个值为 1 的元素vector<int> v3(3, 1);// v3 中包含了 4 个默认值初始化的元素vector<int> v4(4);//使用2, 3, 4初始化 v5vector<int> v5{ 2, 3, 4 };// 二维数组初始化vector<vector<int>> v;
}

vector常用操作

int main() {vector<int> v;// 如果 v 为空则返回 true,否则返回 falsev.empty();// 返回 v 中元素的个数v.size();// 向 vector 的尾端添加值为 1 的元素。// 注意:vector 不支持 push_front 操作。v.push_back(1);// 返回 v 中第 3 个位置上元素的引用,不能用下标操作添加元素int n = v[3];// 删除尾元素,返回void。vector同样 不支持 pop_front 操作。// 若想在同时弹出元素的值,就必须在执行弹出之前保存它(可以使用 v.back())。v.pop_back();// 返回 v 中最后一个元素的引用int m = v.back();// 返回 v 中第一个元素的引用int n = v.front();vector<int> a{ 2, 0, 2, 2, 0, 3, 0, 9 };a.resize(15);  //修改容器大小,变长了用0填充,短了删除尾部元素a.resize(15,100);  // 变长用100填充int n = a.capacity();   //返回容量大小
}

遍历vector

#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;void myPrint(int val) {cout << val << endl;
}int main() {// 创建vector容器vector<int> v;// 向容器的末尾插入数值v.push_back(10);v.push_back(20);v.push_back(30);v.push_back(40);// v.begin()指向第一个元素的迭代器vector<int>::iterator itBegin = v.begin();// v.end()指向最后一个元素的下一个元素的迭代器vector<int>::iterator itEnd = v.end();// 遍历vwhile (itBegin != itEnd) {cout << *itBegin << endl;itBegin++;}// 遍历容器中的元素,并将元素作为参数传递给myPrint函数for_each(v.begin(), v.end(), myPrint);
}

插入数据

int main(void)
{vector<int> a{ 1, 2, 3, };auto it1 = a.begin();  // 返回一个迭代器类型,一般来说我们并不关心迭代器具体的数据类型auto it2 = a.insert((it1 + 1), { 6, 7, 8 });  // 利用迭代器在第二个元素之前插入数据
}

删除元素

int main(void)
{vector<int> a{ 1, 2, 3, };auto it1 = a.begin();  // 返回一个迭代器类型,一般来说我们并不关心迭代器具体的数据类型auto it2 = a.erase(it1 + 1);  // 删除元素 2,返回值为元素删除后被删除元素的当前位置的值
}

容器嵌套


int main() {// 创建vector容器vector<vector<int>> v;vector<int> v1;vector<int> v2;vector<int> v3;vector<int> v4;for (int i = 0; i < 4; i++) {v1.push_back(10);v2.push_back(20);v3.push_back(30);v4.push_back(40);}v.push_back(v1);v.push_back(v2);v.push_back(v3);v.push_back(v4);for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++) {for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++) {cout << *vit << endl;}}
}

算法操作

int main(void)
{vector<int> a{ 2, 0, 2, 2, 0, 3, 0, 9 };sort(a.begin(), a.end());  //排序// 将重复的内容放在末尾,然后删除末尾元素auto end_unique = unique(a.begin(), a.end());a.erase(end_unique, a.end());// 将送其中的元素进行翻转逆序reverse(a.begin(), a.end());// 找到最大值和最小值auto it = max_element(a.begin(), a.end());auto it = min_element(a.begin(), a.end());for (int i : a)cout << i << " ";// 互换容器vector<int> b;a.swap(b);  //将a和b进行互换// 预留100个空间,预留的空间不可访问a.reserve(100);return 0;
}

string

字符串初始化

int main() {// 默认构造string s1;const char* str = "zhangsan";// 通过char数组构造string s2(str);// 通过拷贝构造string s3(s2);// 初始化s4为10个astring s4(10, 'a');
}

字符串幅值

int main() {string s1= "zhangsan";string s2;// 通过另一个字符串进行赋值s2 = s1;string s3;// 赋值一个字符s3 = 'a';// 通过assign赋值s3.assign("lisi");// 将字符串lisishiren的前五个给s3赋值s3.assign("lisishiren", 5);// 将s2的值赋给s3s3.assign(s2);//给s3赋值5个xs3.assign(5,'x');
}

字符串拼接

int main() {string s1= "zhangsan";string s2 = "lisi";// 将s2拼接到s1后面s1 += s2;s1.append(s2);// 追加一个字符s1 += 'c';//追加一个字符串s1 += "lisi";s1.append("lpve");// lpvedfad的前四个字符追加到s1s1.append("lpvedfad",4);//  截取lpvedfad的第4个字符开始的三个字符s1.append("lpvedfad",4,3);
}

查找和替换

在这里插入图片描述

字符串比较

int main() {string s1= "zhangsan";string s2 = "lisi";// 比较s1和s2的大小,n=0相等,n<0则s1小,n>0则s1大int n =  s1.compare(s2);
}

字符存取

int main() {string s1= "zhangsan";// 获取第三个字符s1[3];s1.at(3);// 修改第三个字符s1[3]='x';s1.at(3) = 'x';
}

字符插入和删除

int main() {string s1= "zhangsan";// 在位置1插入111s1.insert(1, "111");// 在位置1后面删除三个字符s1.erase(1, 3);
}

获取字串

int main() {string s1= "zhangsan";// 从第一个字符起截取三个字符s1.substr(1, 3);}

deque

deque是一个双向队列(double-ended queue),可以在队列的两端进行元素的插入和删除操作。
deque的特点是可以在队列的两端进行元素的操作,并且可以高效地在队列的任意位置进行元素的插入和删除操作

//deque的定义 deque<int>d1; //定义一个储存数据类型为int的双端队列d1 push_back()//在队列的尾部插入元素。emplace_front()//与push_front()的作用一样 push_front()//在队列的头部插入元素。emplace_back()//与push_back()的作用一样 pop_back()//删除队列尾部的元素。pop_front()//删除队列头部的元素。back()//返回队列尾部元素的引用。front()//返回队列头部元素的引用。clear()//清空队列中的所有元素。empty()//判断队列是否为空。size()//返回队列中元素的个数。begin()//返回头位置的迭代器end()//返回尾+1位置的迭代器rbegin()//返回逆头位置的迭代器 rend()//返回逆尾-1位置的迭代器 insert()//在指定位置插入元素 erase()//在指定位置删除元素 

list

list容器的底层数据结构为带头双向循环链表,这使得 list的元素可以存储在非相邻的内存中
list 在插入删除元素方面很有优势,在列表的任意位置进行插入和删除操作的时间复杂度为O(1)
不能直接通过位置(下标)来直接访问元素,想要访问list的某个元素,必须从list的一端(或已知位置)迭代到该元素
list还需要额外的存储空间来储存前一个元素和后一个元素的链接信息。
list优点

高效的插入和删除:由于std::list是基于带头双向循环链表实现的,插入和删除操作在任意位置都具有常数时间复杂度O(1),不需要移动其他元素。这使得std::list在需要频繁插入和删除元素的场景下非常高效。
稳定的迭代器:在std::list中进行插入和删除操作不会使得迭代器失效。这意味着在插入或删除元素后,仍然可以继续使用之前获取的迭代器进行遍历和操作。

list的缺点

低效的随机访问
占用额外内存
迭代器不支持指针算术:std::list的迭代器不支持指针算术运算,无法像指针那样直接进行加减操作,这限制了一些操作的灵活性

list构造

list<int> str_a; list<int> lt2(10, 2); //构造含有10个2的int类型容器list<int> lt3(lt2); //拷贝构造int类型的lt2容器的复制品string s("hello world");list<char> lt4(s.begin(), s.end()); //构造string对象某段迭代器区间的内容int arr[] = { 1, 2, 3, 4, 5 };int sz = sizeof(arr) / sizeof(int);list<int> lt5(arr, arr + sz); //构造数组某段区间的复制品  ->本质是调用迭代器区间的构造函数list<int> lt{ 1,2,3,4,5 };  // 直接使用花括号进行构造---C++11允许

list常用接口

int array[] = { 1,2,3,4,5,6,7,8 };list<int> lt(array, array + sizeof(array) / sizeof(array[0]));lt.begin();		//指向第一个元素的迭代器lt.end();		//返回最后一个元素的下一个元素的迭代器lt.rbegin();		//指向最后一个元素的迭代器lt.rend();			//返回第一个元素的前一个元素的迭代器list<int> mylist = { 1, 2 };// 把mylist的大小设为5mylist.resize(5);// 把list大小设为4,不足部分填充5mylist.resize(4, 5);// 判空mylist.empty();mylist.clear(); //清空容器mylist.front();	// 返回头元素mylist.back();	// 返回尾元素// 在list尾部插入一个元素8mylist.push_back(8);// 在list头部插入一个元素8mylist.push_front(8);// 删除mydeue尾部一个元素mylist.pop_back();// 删除mydeue头部一个元素mylist.pop_front();// it指向mylist的第二个元素list<int>::iterator it = mylist.begin() + 1;// 使用insert添加一个元素list<int>::iterator itnew = mylist.insert(it, 10);// 使用insert添加2个元素,value为20mylist.insert(it, 2, 20);list<int> list2{ 10, 20, 30 };// it1指向list2的第一个元素list<int>::iterator it1 = list2.begin();// it2指向list2的最后一个元素后一个位置list<int>::iterator it2 = list2.end();// 使用insert在2之前添加[it1,it2)之间的元素mylist.insert(it, it1, it2);// it指向mylist的第二个元素list<int>::iterator it = mylist.begin() + 1;// 删除it指向的元素,即2,并返回一个迭代器指向2之后的元素list<int>::iterator itnew = mylist.erase(it);// it1指向mylist的第二个元素list<int>::iterator it1 = mylist.begin() + 1;// it2指向mylist的最后一个元素后一个位置list<int>::iterator it2 = mylist.end();// 删除[it1,it2)之间的元素,即删除2,3,4mylist.erase(it1, it2);// 交换list1和list2的元素mylist.swap(list2);// 将list2中所有元素插入到mylist的第一个位置mylist.splice(mylist.begin(), list2);// 将迭代器向后移动两个位置,指向第三个元素std::advance(it, 2);// 将list2的第一个元素(10)插入到mylist的第三个位置mylist.splice(it, list2, list2.begin());std::list<int> list5 = { 1, 2, 3, 4, 5 };std::list<int> list6 = { 10, 20, 30 };// 将list5中第二个到第四个元素移动到list6的末尾auto first = list5.begin();std::advance(first, 1);auto last = list5.begin();std::advance(last, 4);list6.splice(list6.end(), list5, first, last);mylist.remove(2);bool isEven(int n) {return n % 2 == 0;}mylist.remove_if(isEven);mylist.unique();		//删除连续的重复元素 mylist.merge(list2);	//将 list2 合并到 mylist 中,两个列表必须都是完成排序的mylist.reverse();		//将该链表的所有元素的顺序反转
http://www.xdnf.cn/news/6740.html

相关文章:

  • python报错:使用json.dumps()时,报错type xxx is not json serializable错误原因及解决方案
  • 反转链表链表数据结构oj题(206)
  • Spring MVC 中请求处理流程及核心组件解析
  • 2024 睿抗机器人开发者大赛CAIP-编程技能赛-本科组(国赛) 解题报告 | 珂学家
  • React中useMemo和useCallback的作用:
  • 人工智能-状态空间-猴子摘香蕉
  • 从零实现一个高并发内存池 - 4
  • 中级网络工程师知识点3
  • 城市排水管网流量监测系统解决方案
  • HC32L190 串口驱动
  • [ linux-系统 ] 命令行参数 | 环境变量
  • 数据库--向量化基础
  • C++跨平台开发:突破不同平台的技术密码
  • 从硬件角度理解“Linux下一切皆文件“,详解用户级缓冲区
  • 增量学习:机器学习领域中的资源高效利用秘籍
  • HTTPS 加密原理
  • 编译原理概述
  • 将three.js场景保存成图片
  • IEEE PRMVAI 2025 IEEE PRMVAI 探索人工智能在基础设施建设应用与运维中的新挑战
  • 某某建筑市场监管公共服务平台|数据解密—逆向分析
  • rocketmq 环境配置[python]
  • 记录算法笔记(2025.5.15)将有序数组转换为二叉搜索树
  • unity之导入本地packages包
  • 【云实验】搭建个人网盘实验
  • OSM路网简化文档+实操视频讲解(道路中心线提取、拓扑检查,学术论文处理方式)11
  • 日语学习-日语知识点小记-构建基础-JLPT-N4阶段(22):复习
  • AI基础知识(04):技术支柱、核心概念、开发工具、学习路径、伦理与挑战
  • python中常用的参数以及命名规范
  • Python - 爬虫;Scrapy框架之items,Pipeline管道持久化存储(二)
  • 每周靶点:HE4、S100β及文献分享