C++之STL容器

STL有3个主要组件:容器(container)、迭代器(interator)、算法(algorithm)

一、容器

容器封装了一些基本操作,STL容器包括最常用和最重要的数据结构,可以根据特定应用程序相关的数据类型进行调整,而STL算法的实现是与容器无关的。

容器分为顺序容器(sequence container)、关联容器(associative container)、容器适配器(container adapter)
1、顺序容器
顺序容器有3种类型:向量、链表、双端队列。

  • Vector提供了具有连续内存地址的数据结构,可以通过下标运算符随机访问容器中的任意元素。添加元素到向量尾或从向量尾删除元素都不会带来过量的开销,但在向量头部或中间插入和删除就会占用较多时间,因为需要移动元素来腾出空间。
  • List是一种可以双向访问的序列,由一些不相邻的对象组成,这些对象用向前和向后指针连接起来。list允许在任意位置进行插入和删除,而不会带来过量开销。
  • Double-Ended Queue,Deque与Vector类似,不同的是双端队列能在容器头部和末尾快速插入和删除。随机插入和删除占用的开销更大。
    (1)关于Vector

vector是一个动态的序列容器,相当于一个size可变的数组。

相比于数组,vector会消耗更多的内存以有效的动态增长。而相比于其他动态序列容器(deques, lists and forward_lists),vector能更快的索引元素(就像数组一样),而且能相对高效的在尾部插入和删除元素。如果不是在尾部插入和删除元素,效率就没有这些容器高。

当需要使用vector的时候,需要包含头文件:#include <vector>,一般加上using namespace std;如果不加,则在调用时候必须用std::vector<...>这样的形式,即在vector前加上std::,这表示运用的是std命名空间下的vector容器。

常见用法(以int型为例)
声明及初始化

vector<int> a;    //声明一个int型向量a
vector<int> a(10);    //声明一个初始大小为10的向量,类似于int a[10]
vector<int> a(10, 1);    //声明一个初始大小为10且初始值都为1的向量

vector<int> b(a);    //声明并用向量a初始化向量b
vector<int> b(a.begin(), a.begin()+3);    //将a向量中从第0个到第2个(共3个)作为向量b的初始值   

int n[] = {1, 2, 3, 4, 5};
vector<int> a(n, n+5);    //将数组n的前5个元素作为向量a的初值
vector<int> a(&n[1], &n[4]);    //将n[1] - n[4]范围内的元素作为向量a的初值

添加元素

vector<int> a;
a.push_back(1);    //在尾部加入一个数据
a.push_back(2);
a.pop_back();      //删除最后一个数据
a.insert(a.begin(), 0);    //在a.begin()之前加入0
a.erase(a.begin());    //将a.begin()的元素删除
a.erase(a.begin() + 1, a.end());    //将第二个元素以后的元素均删除

注意:任何一个插入操作都将增加vector 的大小,而不是覆盖掉某个现有的元素。程序结束时ivec 包含 14 个元素, ia 的元素从第八个元素开始插入。

const int size = 7; 
int ia[ size ] = { 0, 1, 1, 2, 3, 5, 8 }; 
vector< int > ivec( size ); 

for ( int ix = 0; ix < size; ++ix ) 
      ivec.push_back( ia[ ix ]); 

遍历访问vector

vector<int> a;
//像数组一样以下标访问 
for(int i = 0; i < a.size(); i++)
{
    cout << a[i];
}

//以迭代器访问
vector<int>::iterator it;
for(it=a.begin(); it!=a.end(); it++)
{
    cout<<*it<<" " ;
}

由end操作返回的迭代器指向vector的“末端元素的下一个”。通常称为超出末端迭代器(off-the-end iterator),表明它指向了一个不存在的元素。如果vector为空,begin返回的迭代器与end返回的迭代器相同。

判断vector是否为空

vector<int> a;
if(a.empty())
{
    a.push_back(1);
}

排序必须包含algorithm头文件

#include<algorithm>

vector<int> a;
sort(a.begin(),a.end());

以vector实现二维数组

vector<vector<int>> a(10,vector<int>(5));
#创建一个10行5列的int型二维数组,相当于a[10][5]

(2)关于List
链表也即链式表,在数据结构中,我们知道线性表的物理存储结构有两种,顺序表(数组)和链式表(结点)。链表是在堆中为每一个元素分配内存,然后利用指针将所有元素串起来。根据这种物理存储结构,我们很容易明白:链表在插入、删除效率上比较高,但没有办法随机访问,因此访问速度慢。

当需要使用list的时候,需要包含头文件:#include <list>,list属于std命名域的内容,因此需要通过命名限定:using std::list;也可以直接使用全局的命名空间方式:using namespace std;

常见用法(以int型为例)

声明及初始化

list<int> a{6,7,8,9};
list<int> first;         //空list
list<int> second(4,100); //声明一个初始大小为4且初始值都为100的list
list<int> third(second.begin(),second.end());//将second list中从第0个到最后一个作为list third的初始值 
list<int> forth(third); //从third list的copy

int ints[]={16,2,77,29};
list<int> fifth(ints,ints+sizeof(ints)/sizeof(int));


typedef struct info_s
{
    int nNumber;
}info_t;
//list<info_t> list_t;
typedef std::list< info_t > list_t;

添加元素

second.push_back(20);
second.pop_back();
second.push_front(30);
secnod.pop_front();

second.insert(second.begin(),40);//从前面插入40
second.insert(second.begin(),2,200);//插入2个200
second.insert(second.begin(),third.begin(),third.end());//从前面插入third list的全部元素

second.erase(second.begin());//删除第一个元素
second.erase(second.begin(),second.end());//删除所有元素

注意1:使用pop_back()可以删掉尾部第一个元素,pop_front()可以删掉头部第一个元素。注意:list必须不为空,如果当list为空的时候调用pop_back()和pop_front()会使程序崩掉。

注意2:通过front()可以获得list容器中的头部元素,通过back()可以获得list容器的最后一个元素。注意:当list元素为空时,这时候调用front()和back()不会报错。因此在编写程序时,最好先调用empty()函数判断list是否为空,再调用front()和back()函数。

其他元素操作

second.swap(third);//交换两个list
swap(second,third);

second.resize(10);//将list长度改为只容纳10个元素,超出的元素将被删除
//如果n比list原来的长度长,那么默认超出的部分元素置为0.也可用resize(n,m)
//的方式将超出的部分赋值为m

second.clear(); //清空list中的所有元素

reverse(second.begin(),second.end());//list逆置

second.remove(7);//删除list中指定的元素

second.merge(third);//合并second、third中的元素,third变为空

遍历list

for(list<int>::iterator it=second.begin();it!=second.end();++it)
    cout<<*it<<" ";

判断list是否为空

if(!second.empty())
{
    second.pop_back();
}

(3)关于Deque

参考链接:
https://www.cnblogs.com/YJthua-china/p/6550960.html

https://blog.csdn.net/zhouzhenhe2008/article/details/77428743

https://blog.csdn.net/cypress1010/article/details/53669403

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值