C++ STL?看这篇就够啦。草履虫都能学会的STL教程!

这篇具有很好参考价值的文章主要介绍了C++ STL?看这篇就够啦。草履虫都能学会的STL教程!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

容器是什么?

几乎可以说,任何特定的数据结构都是为了实现某种特定的算法。STL容器就是将运用最广泛的一些数据结构实现出来。
常用的数据结构:数组(array) , 链表(list), tree(树)栈(stack),** 队列(queue)**, 集合(set),映射表(map), 根据数据在容器中的排列特性,这些数据分为序列式容器和关联式容器两种。

  • 序列容器强调值的排序,每个元素有着固定的位置,比如vector,deque,list
  • 关联容器一般是树状结构,方便查找,强调键值对。键起到索引作用,比如map,set

string容器

c语言中char风格字符串(以空字符为结尾的字符组难以掌握),不适合大型程序的开发,所以在头文件<string>内定义了一种string类。与char相比,string是个类而char是个指针,封装了更多的方法,不用考虑内存的释放和越界。

构造函数

string();//创建一个空的字符串 例如: string str;      
string(const string& str);//使用一个string对象初始化另一个string对象
string(const char* s);//使用字符串s初始化
string(int n, char c);//使用n个字符c初始化 
string s(int beg,int end) //以区间beg;end(不包含end)内的字符作为字符串s的初值

常见函数

大小容量函数 作用
size(),length() 返回字符串长度
max_size() 返回当前字符串最多能包含的字符数
capacity() 重新分配内存之前 string所能包含的最大字符数
reserve() 为当前的string重新分配内存,参数为分配内存的大小
元素存取函数 作用
at(),[] 索引不会检查长度在str[str.length()]依然有效,返回值为’\0’
比较函数 作用
>,>=,<,<=,==,!= 按照字典顺序比较
compare() 返回0则相等,支持多参数
更改内容函数 作用
= 赋值
compare() 返回0则相等,支持多参数
assign(str,begin,end) 返回str[begin:end]的值
append() 往后面加字符
push_back() 加单个字符太常见了吧
insert(index,str) 索引index的位置加一个str
replace(1,2,str) 从索引为1开始后两个换成str
erase(7,5) 索引7的位置删除5个,如果形参2没有,默认从参数1索引后面删光
substr(5,6) 提取5到6的子串
find 查找
find_first_of 反 查找包含子串中的任何字符,返回第一个位置
find_first_not_of 查找不包含子串中的任何字符,返回第一个位置
find_last_of 查找包含子串中的任何字符,返回最后一个位置
find_last_not_of 查找不包含子串中的任何字符,返回最后一个位置

vector容器

与array的区别

vector的数据安排以及操作方式,与array非常相似,两者的唯一差别在于空间的运用的灵活性。
与array的区别:使用的 是动态空间,就算内容变动也会自动重新分配内存。两者在内存空间都是连续的内存空间。
动态增长的原理:如果空间不足会申请更大的内存空间,会拷贝到新空间,释放旧空间。

构造函数

vector<T> v; //采用模板实现类实现,默认构造函数
vector(v.begin(), v.end());//将v[begin(), end())区间中的元素拷贝给本身。
vector(n, elem);//复制构造拷贝。
vector(const vector &vec);//拷贝构造。
vector<int> nVec(5,-1);//参数1是vector里面的数量1,参数是赋值
vector<string>str_vec{'a','b'}//注意“()”,“{}”的区别,()是函数,参数里面的是函数。因为是构造函数的形参。一般情况下创建空的然后往里面+数,类似于python中的append()。

std::vector<int>nVec;
for(int i = 0; i<5;++i)
    nVec.push_back(i);

常见函数

函数 作用
insert() 添加元素(函数重载过多次,可以看下面的应用)
push_back() 从后面加一个,效率高,不需要换地址的
pop_back() 删除
size() 大小操作是否为空
resize() 默认值填充,多的直接删除
capacity() 观察容量
vector<int>list{10,9,8,7};
list.insert(pos,num); // 在pos位置插入元素num
list.insert(pos,n,num);   // 在pos位置插入n个元素num重复性数据
list.insert(pos,beg,end);  // 在pos位置插入区间为[beg,end)的元素,自己的元素
c.erase(p);      // 删除迭代器p所指定的元素,返回一个指向被删除元素之后的迭代器。
c.erase(begin,end);   // 删除b,e所指定范围内的元素,返回一个指向被删除元素之后的迭代器。
c.clear();       // 删除所有元素

vector添加元素时会内存自动增长,删除的时候会自动回收吗?
不会!下面分享一个用于节约内存的方法,利用交换swap函数重新分配内存。

vector<int>v;
for (int i = 0;i <100000;++i)
{
    v.push_back(i)
 }
 v.resize(10); //缩小内存空间
 vector<int>(v).swap(v);

迭代器

迭代器是什么?

迭代器是一种抽象的设计理念,通过迭代器可以在不了解容器内部原理的情况下遍历容器。除此之外,STL 中迭代器一个最重要的作用就是作为容器与 STL 算法的粘结剂,只要容器提供迭代器的接口,同一套算法代码可以利用在完全不同的容器中,这是抽象思想的经典应用。
迭代器和C++的指针非常类似,它指向容器中的某个元素,如果需要也可以对容器的值读/写操作。

  • Input itertor (输入迭代器)只读;只支持自增运算
  • Output itertor(输出迭代器)只写;只支持自增运算
  • Forward itertor(前向迭代器)读写;只支持自增运算forward_list,unordered_map / unordered_multimap,unordered_set / unordered_multiset
  • Bidirectional itertor(双向迭代器)读写;支持自增和自减 list set/multiset,map/multimap
  • Random access itertor(随机访问迭代器)读写;支持完整迭代器算数运算 array,vecor,deque
  • stackqueue不支持迭代器

vector迭代代码实现:

#include <iostream>
#include<vector>
 using namespace std;
 int main(){
    vector<int> v{1,2,3,4,5,6};
    vector<int>::iterator it = v.begin()
    for(;*it !=v.end();it++){
        cout << *it <<'';
        }
    return 0;
 }

deque容器

vector容器是单向开口的连续内存空间,deque则是一种双向开口的连续线性空间。所谓的双向开口,意思是可以在头尾两端分别做元素的插入和删除操作,当然,vector容器也可以在头尾两端插入元素,但是在其头部操作效率奇差,需要开辟一块新的内存,无法被接受。
deque是 一种 动态分段连续空间 组成的,

实现原理

deque容器是连续的空间,至少逻辑上看来如此,连续现行空间总是令我们联想到array和vector,array无法成长,vector虽可成长,却只能向尾端成长,而且其成长其实是一个假象,事实上(1) 申请更大空间 (2)原数据复制新空间 (3)释放原空间 三步骤,如果不是vector每次配置新的空间时都留有余裕,其成长假象所带来的代价是非常昂贵的。

C++ STL?看这篇就够啦。草履虫都能学会的STL教程!
deque是由一段一段的定量的连续空间构成。一旦有必要在deque前端或者尾端增加新的空间,便配置一段连续定量的空间,串接在deque的头端或者尾端。Deque最大的工作就是维护这些分段连续的内存空间的整体性的假象,并提供随机存取的接口,避开了重新配置空间,复制,释放的轮回,代价就是复杂的迭代器架构。
既然deque是分段连续内存空间,那么就必须有中央控制,维持整体连续的假象,数据结构的设计及迭代器的前进后退操作颇为繁琐。Deque代码的实现远比vector或list都多得多。

C++ STL?看这篇就够啦。草履虫都能学会的STL教程!

//二叉树的节点
class Linknode
{
publiclinknode(); //构造函数
    int data;
    Linknode* left; //左节点
    Linknode* right;  //右节点	
};
Linknode::linknode()
{
	left =NULL;
	right =Null;
}
class Tree
{
	Linknode* root; //创建二叉树的根
	
}

常见函数

构造函数 作用
dequie<T> deq 默认构造函数
deque(const deque &deq) 拷贝构造函数
deque(beg, end) 拷贝函数,构造函数将[beg, end)区间中的元素拷贝给本身
deque(n, elem) 构造函数将n个elem拷贝给本身
deque赋值操作 作用
assign(beg, end) 将[beg, end)区间中的数据拷贝赋值给本身
assign(n, elem) 将n个elem的值赋给本身
deque& operator=(const deque &deq) 重载=操作符
swap(deq) 交换元素
deque大小操作 作用
deque.size() 返回deque中元素的个数
deque.empty() 返回容器中为空否为真
deque.resize(num) 重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾 超出容器长度的元素被删除。
deque.resize(num, elem) 若分配的内存大于原先的,则用elem填充
deque双端操作 作用
push_back(elem) 在容器尾部添加elem
push_front(elem) 在容器头部添加elem
pop_back(elem) 在容器尾部删除一个元素
pop_front(elem) 在容器头部删除一个元素
deque数据存取 作用
deq(idx) 返回索引idx所指的数据,如果idx越界,抛出out_of_range。
front() 返回容器第一个值
back() 返回容器最后一个值
deque插入 作用
insert(pos,elem) 在pos位置插入一个elem元素的拷贝,返回新数据的位置
insert(pos,n,elem) 在pos位置插入n个elem数据,无返回值
insert(pos,beg,end) 在pos位置插入[beg,end)区间的数据,无返回值
deque删除操作 作用
clear() ` 移除容器的所有数据
erase(beg,end) 删除[beg,end)区间的数据,返回下一个数据的位置
erase(pos) 删除pos位置的数据,返回下一个数据的位置

stack容器 栈

先进后出的容器,只有一个入口和出口,允许新增元素移除元素,取得最顶端元素,但是没有办法获取除了最顶端元素之外的元素,不允许有 遍历 行为和 迭代 行为!
C++ STL?看这篇就够啦。草履虫都能学会的STL教程!

常见函数

API 作用
push(elem) 向容器添加elem
pop() 移除容器第一个元素(栈顶)
top() 返回栈顶元素
empty() 判断是否为孔
size() 返回大小

queue容器

queue是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口,queue容器允许从一端新增元素,从另一端移除元素。与栈·一样没有迭代器
C++ STL?看这篇就够啦。草履虫都能学会的STL教程!

常见函数

API 作用
push(elem) 向容器添加elem
pop() 移除容器第一个元素(栈顶)
back() 返回最后一个元素
front() 返回第一个元素
empty() 判断是否为孔
size() 返回大小

list容器 链表

链表的概念

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
list和vector是最常见的被使用的容器:

  • 采用动态存储分配,不会造成内存浪费和溢出
  • 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
  • 链表灵活,但是空间和时间额外耗费较大
    C++ STL?看这篇就够啦。草履虫都能学会的STL教程!
    写成代码(随便写写,意思到了就行)就是:
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
struct ListNode
{
	int data;
	ListNode* next;//结构体指针
};
void Listprintf(ListNode* phead)
{
	ListNode* cur=phead;
	while (cur != NULL)
	{
		cout << cur->data << "->";
		cur = cur->next;
	}
}
void Listpushback(ListNode** pphead, int x)
{
	ListNode* newnode = new ListNode{ x,NULL };
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		ListNode* tail=  *pphead;
		while(tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}
void test_1()
{
	ListNode* phead = NULL;
	Listpushback(&phead, 1);
	Listpushback(&phead, 2);
	Listpushback(&phead, 3); 
	Listprintf(phead);
}
int main()
{
	test_1();
	return 0;
}

list容器的迭代器

list的迭代器不能像一些连续内存的容器中那样是指针,它需要的是利用递增递减可以前后捕捉每个节点的next和pre的能力。可以看上面代码如果指针没有指向null则会一直指向下一个Node的地址。

常见函数

构造函数 作用
list<T> lstT list采用采用模板类实现,对象的默认构造形式:
list(beg,end) 构造函数将[beg, end)区间中的元素拷贝给本身。
list(n,elem) 构造函数将n个elem拷贝给本身。
list(const list &lst) 拷贝构造函数
赋值函数 作用
push_back(elem) 在容器尾部加入一个元素
pop_back() 删除容器中最后一个元素
push_front(elem) 在容器开头插入一个元素
pop_front() 从容器开头移除第一个元素
insert(pos,elem) 在pos位置插elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem) 在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end) 在pos位置插入[beg,end)区间的数据,无返回值。
clear() 移除容器的所有数据
erase(beg,end) 删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos) 删除pos位置的数据,返回下一个数据的位置。
remove(elem) 删除容器中所有与elem值匹配的元素。
大小操作 作用
size() 返回容器中元素的个数
empty() 判断容器是否为空
resize(num) 重新指定容器的长度为num
resize(num, elem) 重新指定容器的长度为num
赋值操作 作用
assign(beg, end) 将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem) 将n个elem拷贝赋值给本身。
list& operator=(const list &lst) 重载等号操作符
swap(lst) 将lst与本身的元素互换。
reverse() 反转链表,比如lst包含1,3,5元素,运行此方法后,lst就包含5,3,1元素。
sort() list排序

set/multiset容器

set/multiset属于关联式容器,底层结构使用二叉树 实现的。它们的特点是:所有的元素的键值在插入时会自动被排序。不可以用迭代器改变set的值,因为如果动了其中一个值会影响整个的树的结构。而set与multiset容器的区别就是:set容器中不允许有重复的元素,而multiset允许容器中有重复的元素。

二叉树

树状图 是一种数据结构,它是由 n(n>=1)个有限结点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:
每个结点有零个或多个子结点;没有父结点的结点称为根结点;每一个非根结点有且只有一个父结点;除了根结点外,每个子结点可以分为多个不相交的子树。由于线性查找需要遍历全部数据,在数据量大的时候效率就非常低下,到底有多低,在数据库有几百万几千万以上数据量写过查询语句的就知道有索引和没索引的区别。
C++ STL?看这篇就够啦。草履虫都能学会的STL教程!
代码实现:

//二叉树的节点
class Linknode
{
publiclinknode(); //构造函数
    int data;
    Linknode* left; //左节点
    Linknode* right;  //右节点	
};
Linknode::linknode()
{
	left =NULL;
	right =Null;
}
class Tree
{
	Linknode* root; //创建二叉树的根
	
}

常见函数

构造函数 作用
set<T> st set默认构造函数:
mulitset<T> mst multiset默认构造函数:
set(const set &st) 拷贝构造函数
赋值函数 作用
set& operator=(const set &st) 重载等号操作符
swap(st) 交换两个集合容器
大小操作 作用
size() 返回容器中元素的数目
empty() 判断容器是否为空
插入和删除操作 作用
insert(elem) 在容器中插入元素。
clear() 清除所有元素
erase(pos) 删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg, end) 删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(elem) 删除容器中值为elem的元素。
查找操作 作用
find(key) 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
count(key) 查找键key的元素个数
lower_bound(keyElem) 返回第一个key>=keyElem元素的迭代器。
upper_bound(keyElem) 返回第一个key>keyElem元素的迭代器。
equal_range(keyElem) 返回容器中key与keyElem相等的上下限的两个迭代器。

map/multimap容器

map的特性是,所有元素都会根据元素的键值自动排序。
map所有的元素都是关联的,同时拥有实值和键值(key,value),第一元素被视为键值,第二元素被视为实值,map不允许两个元素有相同的键值.

  • map中的key是唯一的。集合中元素按照一定顺序排列。元素的插入按照规则插入我,所以不能指定插入位置。
  • map的底层是红黑树的变体,平衡二叉树。在插入操作、删除和检索上要比vector快很多。
  • map可以直接存取key所对应的value,支持[]操作符,如map[key]=value.
  • #include<map>
  • map支持唯一键值,每个键只能出现一次;而multimap中相同键可以出现多次。multimap不支持[]操作符

map和set的区别是:

Map对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。构造函数Map可以接受一个数组作为参数。
Set对象允许你存储任何类型的,无论是原始值或者是对象引用。它类似于数组,但是成员的值都是唯一的,没有重复的值。文章来源地址https://www.toymoban.com/news/detail-429758.html

#include<map>
#include<iostream>
using namespace std;
int main(void)
{
    multimap<int ,string> james;
    james.insert(pair<int,string>(3,'dog'));
    james.insert(pair<int,string>(4,'cat'));
    //遍历操作
    for (multimap<int,string>::iterator it = james.begin();it !=james.end();it++)
    {
        cout <<(*it).first <<endl;
    }
}

到了这里,关于C++ STL?看这篇就够啦。草履虫都能学会的STL教程!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux,看这篇就够了

    因为我们要部署服务,Linux系统一直以其稳定性而闻名,它们可以连续运行多年而不发生任何重大问题。事实上,很多Linux用户都从未在自己的环境中遇到过系统崩溃的情况。相对windows而言,挂起和崩溃完全是一种常态。 Windows由于是商业产品,源代码封闭,我们无法知道微软

    2024年02月08日
    浏览(45)
  • Ubuntu22.04搭建k8s集群,看这一篇就够啦!

    系统 CPU RAM IP 网卡 主机名 Ubuntu22.04 2 4G 192.168.247.100 NAT k8s-master Ubuntu22.04 2 4G 192.168.247.101 NAT k8s-slave1 Ubuntu22.04 2 4G 192.168.247.102 NAT k8s-slave2 修改主机名 配置hosts映射 关闭防火墙 关闭selinux 关闭交换分区(为了保证 kubelet 正常工作,必须禁用交换分区) 转发 IPv4 并让 iptables 看到桥接

    2024年02月16日
    浏览(40)
  • 测试基本理论-看这篇就够了

    软件测试(Software Testing): 在规定的条件下对程序进行操作,以发现程序错误,衡量软件质量,并对其是否能满足设计要求进行评估的过程。 【系统软件】:如操作系统、数据库管理系统,各种驱动软件等; 【应用软件】:如Office、有道翻译、QQ等; 【单机版本】:如Office,

    2024年02月06日
    浏览(49)
  • 面向对象编程,看这篇就够了

    面向对象编程,是一种程序设计范式,也是一种编程语言的分类。它以对象作为程序的基本单元,将算法和数据封装其中,程序可以访问和修改对象关联的数据。这就像我们在真实世界中操作各种物体一样,比如我们可以打开电视、调整音量、切换频道,而不需要知道电视的

    2024年02月05日
    浏览(79)
  • 关于SpringBoot框架,看这篇就够了。

    目录 是什么 有什么优点、解决了哪些问题 创建第一个以springboot项目 starter 核心配置文件application.yml或properties application中的配置项 springboot的启动流程 自定义banner 整合日志打印 整合druid数据源 处理异常 常用的注解 Configuration Import conditional ConfigruationProperties 基于springboot的

    2024年02月06日
    浏览(50)
  • 倾向得分匹配只看这篇就够了

    倾向得分匹配模型是由Rosenbaum和Rubin在1983年提出的,首次运用在生物医药领域,后来被广泛运用在药物治疗、计量研究、政策实施评价等领域。倾向得分匹配模型主要用来解决非处理因素(干扰因素)的偏差。 ‍1、基本原理——反事实推断 基本原理是 :根据处理组的特征,

    2024年02月05日
    浏览(47)
  • Redis基础命令汇总,看这篇就够了

    本文首发于公众号:Hunter后端 原文链:Redis基础命令汇总,看这篇就够了 本篇笔记将汇总 Redis 基础命令,包括几个常用的通用命令,和各个类型的数据的操作,包括字符串、哈希、列表、集合、有序集合等在内的基本操作。 以下是本篇笔记目录: 通用命令 字符串命令 哈希

    2024年02月04日
    浏览(50)
  • ElasticSearch自定义评分-看这篇就够了

    文章目录   一、适用的场景    1.基本介绍    2.使用场景     2.1根据价格评分排序     2.2根据距离评分排序     2.3根据距离价格综合评分排序     2.4自定义编写脚本   二、常用的字段解释    1.整体结构    2.function_score     2.1.qu

    2024年02月06日
    浏览(44)
  • 自学黑客(网络安全)看这篇就够了

    写了这么多编程环境和软件安装的文章,还有很多小伙伴在后台私信说看不懂。我都有点头疼了,但是小伙伴们求学的心情我还是能理解,竟然这么多人给我反馈了,那我就再写一篇网络安全自学的教程吧!大家耐心看完,后面有惊喜。 一、自学网络安全的误区和陷阱 1.不要

    2024年02月06日
    浏览(60)
  • 关于信贷评分卡模型,看这篇就够了!

    风险并不是所有人都能轻松看到,信贷公司同样如此。 8月4日下午15:00,顶象研发总监就评分卡模型展开分享,详细介绍了评分卡模型的原理、评分卡模型的构建过程、评分卡模型的开发投产以及顶象的评分卡模型实践。 评分卡模型原理 通常来说,我们把贷款分为抵押贷款

    2024年02月12日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包