c++/STL标准库中常用容器

本文详细介绍了C++STL(标准模板库)的核心组成部分,包括容器(如vector、list、deque、set、map等)、算法以及迭代器。重点讲解了vector的特点、创建方法和操作,以及list、deque和映射容器的特性与用法。
摘要由CSDN通过智能技术生成

STL(Standard Template Library,标准模板库),是惠普实验室开发的一系列软件的统称。现在主要出现在 c++中,但是在引入 c++之前该技术已经存在很长时间了。ttps://blog.csdn.net/weixin

C++ STL(Standard Template Library,标准模板库)是一套强大的C++模板类集合,它提供了许多高效的数据结构和算法。

STL的核心包括三个组成部分:

容器(Containers):用于存储数据的对象,例如vector、list、deque和map。容器是用来管理对象集合的工具,可以容纳不同类型的数据,并且支持对其内容进行添加、删除和访问等操作。

算法(Algorithms):作用于容器上的通用函数,提供了一系列标准化的操作方式,如对容器内容执行初始化、排序、搜索和转换等操作。

迭代器(Iterators):用于遍历容器中的元素。迭代器提供了一种通用的接口来访问容器内的元素,使得算法能够以统一的方式处理不同的容器类型。

其中容器:

STL中常用的容器包括vector、list、deque、set、map、unordered_set和unordered_map等。具体如下:

vector:

它是一个动态数组,支持随机访问,适合在末尾快速添加或删除元素。由于其连续的内存布局,它也适合进行快速的迭代操作。

特性:

  • vector特别擅长在尾部进行插入和删除操作,这些操作的时间复杂度为O(1)。在容器的头部或中部进行插入或删除操作时,时间复杂度则为线性阶O(n),因为需要移动元素来维护连续内存布局。

创建方法:

  • 创建一个空的vector容器,如vector<double> values;当添加第一个元素时,vector会自动分配内存。
  • 指定初始值及元素个数,如vector<int> primes {2, 3, 5, 7, 11, 13, 17, 19};,这样创建了一个含有8个素数的vector容器。
  • 也可以只指定元素个数,如vector<double> values(20);,这会创建一个有20个元素的vector,默认初始值为0。
  • 通过其他同类型容器来创建新的vector,如使用数组初始化std::vector<int> values(array, array+2);
  • 添加元素的方法:push_back()emplace_back()是两种常用的添加元素到vector尾部的方法。其中,emplace_back()直接在容器末尾构造元素,避免了额外的拷贝或移动操作,通常更高效。

此外,vector支持多种操作,如访问元素、修改元素、排序、反转等。例如,使用v[index]可以访问vector中特定位置的元素,而v.size()则可以获取当前vector的大小。

#include "stdafx.h"
#include <iostream>
 
#include <vector>
using namespace std;
 
int main()
{
   vector<int>  v1;//构造一个空的vector
   cout << "容量为:"<<v1.capacity() << "     元素个数: " << v1.size() << endl;
 
   vector<int>  v2(5);//构造一个空间大小为5,并且元素为5个(有默认值)的vector
   cout << "容量为:" << v2.capacity() << "     元素个数: " << v2.size() <<"	   v2[0]:"<<v2[0]<< endl;
 
   vector<int>  v3(5,111);//构造一个空间大小为5,并且元素为5个(每个元素初始值为111)的vector
   cout << "容量为:" << v3.capacity() << "     元素个数: " << v3.size() << "	   v3[0]:" << v3[0] << endl;
 
   vector<int>  v4(v3);//拷贝构造vector
   cout << "容量为:" << v4.capacity() << "     元素个数: " << v4.size() << "	   v4[0]:" << v4[0] << endl;
 

 
   for (size_t i = 0; i < v2.size(); i++)
   {
   	//cout << v2[i] << "	";
   	//cout << v2.at(i)<< "	";
        cout << &v2[i] << "	";//输出地址,说明存储空间是连续的
   }
   cout << endl;
 
   return 0;
}

//capacity函数用于查询容器的容量,即它能够存储的元素数量。

在C++中,capacity函数通常与vector容器相关联,因为vector在内存中连续存储元素,并且可以预分配一块内存空间来提高性能。对于其他类型的容器,如listmapset等,由于它们的元素在内存中散布,不预分配内存,所以这些容器没有capacity成员函数。

具体到vector容器,capacity指的是容器在不重新分配内存的情况下能够存储的元素数量。这与size不同,size是指容器实际存储的元素数量。当vector需要增长以容纳更多元素时,它的容量通常会增加,以避免频繁的内存重新分配操作。具体的增长策略可能因编译器而异,但通常是增加到原容量的1.5倍或者翻倍。

此外,可以通过构造函数指定vector的初始容量,例如使用vector(n, value=T())构造函数,其中n是指定的容量,value是元素的初始值。如果不指定容量,那么vector的默认容量取决于实现,例如对于std::string类型的vector,默认容量可能是15。

list:

它是一个双向链表,支持在任何位置高效地插入或删除元素,但不支持随机访问

list容器的基本概念是它以双向链表的形式实现,这意味着它的元素可以分散存储在内存空间中,而不是必须存储在一整块连续的内存空间里。这种结构使得list在插入和删除操作上具有优势,尤其是在链表的中间位置进行操作时,因为这些操作不需要移动其他元素,只需要改变指针的指向即可。

list容器的特点包括:

  • 插入和删除操作:由于list是基于链表的,它可以在常数时间内完成在头部或尾部的插入和删除操作。而在中间位置的插入和删除也非常高效,因为只需要修改相邻元素的指针即可。
  • 访问操作:虽然list不支持随机访问,但提供了双向遍历的能力,可以通过迭代器进行顺序或逆向访问。
  • 内存分配:list的元素在内存中是非连续存储的,每个元素都是一个节点,包含数据和指向前后元素的指针。
  • 成员函数:list提供了一系列成员函数来操作元素,如push_front()push_back()pop_front()pop_back()等,这些函数允许在list的不同位置添加或移除元素
     

deque :

它是一个双端队列,支持在两端快速添加或删除元素,同时支持随机访问,适合需要从两端操作数据的场景。

deque(双端队列)是一种线性容器,它允许在两端快速地插入和删除元素。与vector不同,deque的内部结构被设计为分段连续的内存空间,这使得在两端进行操作时不需要移动其他元素,从而保持了高效的性能。以下是deque的一些详细用法:

  • 创建deque容器:可以通过多种方式创建deque容器。例如,创建一个空的deque容器,可以直接声明一个没有元素的deque对象,如std::deque<int> d;这样的容器在创建后可以进行添加或删除元素的操作。
  • 头尾操作:由于deque是双向开口的,它可以在头部和尾部进行高效的插入和删除操作。这对于需要在这些位置频繁操作的数据结构来说是非常有用的。
  • 中间操作:虽然deque在头部和尾部的操作效率很高,但在中间部分插入元素会比较费时,因为这需要移动其他元素来腾出空间。

 

头文件:使用deque之前,需要包含相应的头文件#include <deque>,并且因为它属于std命名域,所以通常需要使用using std::deque;来简化代码。

总的来说,deque容器特别适合那些需要在两端进行频繁操作的场景,如实现一个先进先出(FIFO)的数据结构或者模拟队列的行为。在选择使用deque时,应考虑到其特点和优势,以便更有效地处理特定的数据操作需求。

set:

它是一个集合,内部元素按特定顺序排列,适合快速查找元素。它不允许存储重复的元素,适用于需要去重和有序存储的场合。

set容器是一种关联式容器,它能够存储一组元素并自动保证它们按照一定的次序排列。

首先,需要包含相应的头文件#include <set>,并使用std::set来定义一个集合。set容器可以存储各种类型的数据,包括基本数据类型、结构体、类对象等。

创建set容器的方法有以下几种:

  • 默认构造函数:通过调用默认构造函数创建一个空的set容器。例如,std::set<std::string> myset; 这将创建一个空的set容器,其中的元素会按照默认的升序排序规则(std::less<T>)进行排序。
  • 初始化构造函数:在创建set容器的同时进行初始化。例如,std::set<int> s(s1); 这将用另一个集合s1来初始化新创建的集合s
  • 范围构造函数:使用迭代器的范围来初始化集合。例如,std::set<int> s(b, e); 这里be是迭代器的开始和结束标记。

此外,set容器还支持赋值操作和大小操作。赋值操作可以通过重载等号操作符实现,例如set& operator= (const set &st);。大小操作包括返回容器中元素的数目的size()函数和判断容器是否为空的empty()函数。

map:

 它是一个映射,允许通过键来快速访问对应的值。内部元素按键的顺序排列,适合构建快速查找的键值对集合。

map容器是一种关联式容器,它允许用户存储键值对,并且能够高效地进行查找和排序操作。

首先,使用map之前需要包含相应的头文件#include <map>,并且为了方便使用,通常还需要添加using namespace std;。这样,就可以在代码中定义和操作map了。

接下来是一些关于map的基本用法:

  • 声明map变量:可以声明一个map类型的变量,例如std::map<std::string, int> myMap;,这将创建一个空的map,其中键是字符串类型,值是整数类型。
  •  插入元素:向map中插入元素可以使用insert()函数或者通过下标操作符[]。例如,myMap.insert(std::make_pair("apple", 1));myMap["apple"] = 1;都会将键值对("apple", 1)添加到map中。
  •  查找元素:可以通过键来查找对应的值,如果键存在于map中,下标操作符会返回对应的值,否则会插入一个新的键值对。例如,int value = myMap["apple"];会查找键为"apple"的值。
  • 删除元素:可以使用erase()函数来删除指定的键值对,例如myMap.erase("apple");会删除键为"apple"的元素。
  •  清空map:使用clear()函数可以清空map中的所有元素,例如myMap.clear();会移除所有键值对。    

unordered_set :

它是一个无序集合,与set相似,但不保证元素的顺序,因此查找速度通常更快。

unordered_map:

它是一个无序映射,与map相似,但不保证键的顺序,因此根据键查找值的速度通常更快。

 

 

  • 32
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值