STL提供很多容器,每种容器都提供一组操作行为。序列容器只提供插入功能,其中的元素都是有序的,但未排序。序列容器包括:vector向量,deque双端队列和list双向串行。
这篇博客要写的就是序列容器的三个具体的使用方式,不同以及类似之处。
向量类模板(vector)
向量(vector)是一种随机访问的数组类型,提供了对数组的快速,随机访问,以及在序列尾部的快速插入与删除的处理。它是大小可变的向量,在需要时可以改变向量的大小。
创造vector对象有以下的方式:
std::vector<type> name;
该方式创造了一个名字为name的空vector的对象,type表示存储的数据类型。
例如 创造一个整型数据如下:
std::vector<int> intvector;
还有以下创造方式:
std::vector<type> name(size);
//该方法初始化具有size元素个数的vector对象
std::vector<type> name(size,value);
//该方式创造了一个有size个元素的对象并且初始值都为value
std::vector<type> name(myvector);
//该方法使用复制构造函数,用现有的向量myvector创造了一个vector对象
std::vector<type> name(first,last>;
//该方式创造了元素在指定范围内的向量,first代表起始范围,last代表结束范围
vector对象的主要成员继承了随机接入容器,反向插入序列。
主要成员函数如下:
函数 | 说明 |
assign(first,last) | 用迭代器first和last所辖范围内的元素替换向量元素 |
assign(num.val) | 用val的num个副本替换向量元素 |
at(n) | 返回向量中第n个元素的值(下标从0开始) |
back | 返回对向量末尾元素的引用 |
begin | 返回指向向量中第一个元素的迭代器 |
capacity | 返回当前向量最多可以容纳多少个元素 |
clear | 删除向量中所有的元素 |
empty | 如果向量为空,则返回TRUE值(判断是否为空) |
end | 返回指向向量中最后一个元素的迭代器 |
erase(start,end) | 删除迭代器start和end所辖范围内的向量元素 |
erase(i) | 删除迭代器i所指的元素 |
front | 返回对向量起始元素的引用 |
insert(i,x) | 把值x插入向量中由迭代器i所指的位置 |
insert(i,n,x) | 把x的n个副本插入到向量中由迭代器i所指明的位置 |
max_size | 返回向量的最大容量(最多可以容纳的元素个数) |
pop_back | 删除向量中的最后一个元素 |
push_back(x) | 在向量末尾添加一个值x |
rbegin | 返回一个反向迭代器,指向向量末尾元素之后 |
rend | 返回一个反向迭代器,指向向量起始元素 |
reverse | 颠倒元素的顺序 |
resize(n,x) | 重新设置向量的大小,新元素的值初始化为x |
size | 返回向量的大小(元素个数已经存在的) |
swap(vector) | 交换两个向量的内容 |
insert(i,start,end) | 把迭代器start和end所辖范围内的元素插入到向量由迭代器i所指明的位置 |
彩色所标注的都是与迭代器相关的一些函数操作,使用这些函数时需要特别注意。
下面通过一些实例进一步了解vector模板类的使用方式:
vector模板类使用
#include<iostream>
#include<vector>
#include<tchar.h>
using namespace std;
int main()
{
vector<int> v1,v2;
v1.reserve(10);
v2.reserve(10); //手动分配空间,设置容器元素最小值
v1.push_back(4); //调用push_back(x),将值赋给v1
v1.push_back(5);
v1.push_back(2);
v1.push_back(9);
int arry[8] = {1,7,6,4,2,5,11,35};
v2 = vector<int>(arry,arry+8);
cout << "输出v1的各个元素"<<endl;
for(int i = 0; i < v1.size(); i++) //调用size函数找到v1的元素个数
{
cout<<" "<<v1[i];
}
cout<<endl;
cout << "输出v2的各个元素"<<endl;
for(int i = 0; i < v2.size(); i++) //调用size函数找到v2的元素个数
{
cout<<" "<<v2[i];
}
cout<<endl;
v1.pop_back(); //删除v1的最后一个元素
v2.clear(); //清空v2中的数据元素
cout << "输出pop_back()后 v1的各个元素"<<endl;
for(int i = 0; i < v1.size(); i++) //调用size函数找到v2的元素个数
{
cout<<" "<<v1[i];
}
cout<<endl;
cout << "输出clear()后 v2的各个元素"<<endl;
for(int i = 0; i < v2.size(); i++) //调用size函数找到v2的元素个数
{
cout<<" "<<v2[i];
}
cout<<endl;
return 0;
}
运行结果如下:
在给v1数据是利用了push_back()函数,给其尾部一直加入数据,所以最后加入的数据就在v1的最后。给v2赋值是是利用了数组的赋值方式即创造方式的最后一条std::vector<type>name(first,last).将范围内的数据赋给v2。随后使用pop_back()函数将v1最后的数据删除掉,利用clear将v2所有的数据全部清除掉。
还有一些是使用迭代器 的操作例如如下:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int>v1;
v1.reserve(10);
int array[5] = {1,17,30,24,5};
v1 = vector<int>(array,array+5);
cout << "经过操作之前的v1各数据:" << endl;
for(int i = 0; i < v1.size(); i++)
{
cout << " " << v1[i];
}
cout << endl;
v1.erase(v1.end()-2); //删除了v1中倒数第二个元素
v1.insert(v1.begin()+2,21); //在v1正数第三个位置中加入了21
cout << "输出经过erase(-2),insert(2,21)操作后的v1各数据"<<endl;
for(int i = 0; i < v1.size(); i++)
{
cout << " " << v1[i];
}
cout << endl;
return 0;
}
运行结果如下:
注意 如果是要使用迭代器才可以执行的函数在函数()内需要用end()函数或begin()函数指向要操作的位置。
同样该vector可以存储各种数据,例如一下存储字符串类型:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<string> v1;
v1.push_back("我的好闺蜜:小元同学。");
v1.push_back("属于我的小牧同学!");
for(int i=0;i<v1.size();i++)
{
cout<<v1[i]<<endl;
}
return 0;
}
运行结果如下:
博客就是写出自己的理解,其想法可以天马行空,也可以简简单单,希望到这里你们也可以利用vector写出一个自己的程序,并且去执行如果没有成功不要灰心改一改代码,你会收获的更多哟。
双端队列类模板 (deque)
双端队列是一种随机访问的数据类型,提供了在序列两端快速插入和删除操作的功能,简化了插入和删除数据的方式,他可以在需要的时候修改其自身的大小。
其创造方式与vector创造方式相同。
std::deque<type> name(size);
//该方法初始化具有size元素个数的vector对象
std::deque<type> name(size,value);
//该方式创造了一个有size个元素的对象并且初始值都为value
std::deque<type> name(myvector);
//该方法使用复制构造函数,用现有的向量myvector创造了一个vector对象
std::deque<type> name(first,last>;
//该方式创造了元素在指定范围内的向量,first代表起始范围,last代表结束范围
下面是deque对象主要成员函数及其说明(很重要!!):
函数 | 说明 |
assign(first,last) | 用迭代器first和last所辖范围内的元素替换双端队列元素 |
assign(num.val) | 用val的num个副本替换双端队列的元素 |
at(n) | 返回双端队列中第n个的值 |
back | 返回一个对双端队列最后一个元素的引用 |
begin | 返回指向双端队列中第一个元素的迭代器 |
clear | 删除双端队列中所有的元素 |
empty | 判断是否为空,为空则返回true |
end | 返回指向双端队列最后一个元素的迭代器 |
erase(start,end) | 删除迭代器start和end所辖范围内的双端队列的元素 |
erase(i) | 删除迭代器i所指向的元素 |
front | 返回一个对双端队列第一个元素的引用 |
insert(i,x) | 把值x插入向量中由迭代器i所指明的位置 |
insert(i,start,end) | 把迭代器start和end所辖范围内的元素插入双端队列迭代器i所指的位置 |
insert(i,n,x) | 把x的n个副本插入到双端队列中由迭代器i所指的位置 |
max_size | 返回双端队列的最大容量(最大可以容纳元素的个数) |
pop_back | 删除双端队列的最后一个元素 |
pop_front | 删除双端队列的第一个元素 |
push_back(x) | 把x的值加入到队列尾部 |
push_front(x) | 把x的值加入到队列头部 |
rbegin | 返回一个反向迭代器,指向双端队列最后一个元素之后 |
rend | 返回一个反向迭代器,指向双端队列第一个元素 |
resize(n,x) | 重新设置双端队列的大小,并赋初值为x |
size | 返回双端队列的大小(元素的个数) |
swap(deque) | 交换两个双端队列的值 |
彩色所标注的都是与迭代器相关的一些函数操作,使用这些函数时需要特别注意。
双端队列类模板应用的例子:
#include<iostream>
#include<deque>
using namespace std;
int main()
{
deque<int> d1,d2;
int arry[4] = {5,24,3,21};
d1 = deque<int>(arry,arry+4);
d2.push_front(6); //front是在队列前面加数据
d2.push_front(10);
d2.push_front(9);
cout << "输出未经过任何操作的d1,d2:" << endl; //遍历d1,d2
for(int i = 0; i < d1.size(); i++)
{
cout << " " << d1[i];
}
cout << endl;
for(int i = 0; i < d2.size(); i++)
{
cout << " " << d2[i];
}
cout << endl;
d1.pop_front(); //删除d1的第一个元素
d2.pop_back(); //删除d2的最后一个元素
cout<<"输出经过pop_front()和pop_back操作的d1,d2:"<<endl; //遍历d1,d2
for(int i = 0; i < d1.size(); i++)
{
cout << " " << d1[i];
}
cout << endl;
for(int i = 0; i < d2.size(); i++)
{
cout << " " << d2[i];
}
cout << endl;
d1.swap(d2); //交换d1和d2的元素
cout<<"输出交换后的d1,d2:"<<endl; //遍历d1,d2
for(int i = 0; i < d1.size(); i++)
{
cout << " " << d1[i];
}
cout << endl;
for(int i = 0; i < d2.size(); i++)
{
cout << " " << d2[i];
}
cout << endl;
return 0;
}
程序初始时定义了两个双端队列对象,一个利用赋值的最后一个创造,一个利用push_front将数据存储在对象之中。
运行结果如下:
双端队列对迭代器函数的使用与向量类一样,如果有什么不明白的可以评论或者私信我,一一解答,上面的向量类模板使用时也用过迭代器的函数也可以参考上面的代码进行使用。
链表(list)类模板
链表,即双向链表容器,它不支持上面两类的随机访问,访问链表元素要指针从链表的某个端点开始,插入和删除操作所花费的时间是固定的,和该元素在链表中所在的位置无关。list在任何位置插入和删除动作都很快,不像vector只能在尾端进行操作。
该创建与上两类的创建方式相同:
std::list<type> name(size);
//该方法初始化具有size元素个数的vector对象
std::list<type> name(size,value);
//该方式创造了一个有size个元素的对象并且初始值都为value
std::list<type> name(myvector);
//该方法使用复制构造函数,用现有的向量myvector创造了一个vector对象
std::list<type> name(first,last>;
//该方式创造了元素在指定范围内的向量,first代表起始范围,last代表结束范围
list对象的主要函数成员以及说明如下;
函数 | 说明 |
assign(first,last) | 用迭代器first和last所辖范围内元素替换链表元素 |
assign(num.val) | 用val的num个副本替换链表元素 |
back | 返回一个对链表最后一个元素的引用 |
begin | 返回指向链表中第一个元素的迭代器 |
clear | 删除双链表中所有元素 |
empty | 判断是否为空,为空则返回true |
end | 返回指向链表最后一个元素的迭代器 |
erase(start,end) | 删除迭代器start和end所辖范围内的元素 |
erase(i) | 删除迭代器i所指向的元素 |
front | 返回一个对链表第一个元素的引用 |
insert(i,x) | 把x的值插入链表中由迭代器i所指明的位置 |
insert(i,start,end) | 把迭代器start和end所辖范围内的元素插入链表中迭代器i所指的位置 |
insert(i,n,x) | 把x的n个副本插入到链表中由迭代器i所指明的位置 |
max_size | 返回链表最大容量 |
pop_back | 删除链表最后一个元素 |
pop_front | 删除链表第一个元素 |
push_back(x) | 把x插入链表的尾部 |
push_front(x) | 把x插入链表的头部 |
rbegin | 返回一个反向迭代器,指向链表最后一个元素之后 |
rend | 返回一个反向迭代器,指向链表第一个元素 |
resize(n,x) | 重新设置链表的大小,并赋值为x |
reverse | 颠倒链表元素的顺序 |
size | 返回链表的大小 |
swap(listref) | 交换两个链表的内容 |
彩色所标注的都是与迭代器相关的一些函数操作,使用这些函数时需要特别注意。
下面是链表类模板应用的实例:
对链表各个元素访问,通常使用的是迭代器。
#include<iostream>
#include<list>
using namespace std;
int main()
{
int arry[8]={5,24,3,21,10,9,45,71};
list<int> l1(arry,arry+8);
list<int>::iterator it = l1.begin();
//list的it不支持+运算符
cout << "未排序时的链表元素:" << endl;
for(int i = 0; i < l1.size() ;i++,it++)
{
cout << " " << *it;
}
cout << endl;
l1.sort(); //利用链表排序
cout << "排序后链表元素为:" << endl;
for(list<int>::iterator i = l1.begin(); i!=l1.end(); i++)
{
cout << " " << *i;
}
cout << endl;
l1.pop_back(); //删除链表尾部元素
l1.insert(l1.end(),31);
//在链表尾部插入了31
cout << "经过操作后的链表元素:" << endl;
for(list<int>::iterator i = l1.begin(); i != l1.end(); i++)
{
cout << " " << *i;
}
cout << endl;
return 0;
}
链表模板的应用对迭代器的使用是非常多的,所以想要掌握链表的操作首先先了解迭代器的应用。
迭代器iterator类和指针用法很相似,支持自增操作符,并且通过“*”可以访问相应的对象内容。但list中的迭代器不支持“+”号运算符,而指针与vector中的迭代器都支持。
这篇博客到这里就结束了,这应该算是我写的最长的一片博客了,就此感谢小元同学以及小牧同学的客串,让我了解掌握了使用string类型的数据用模板来表示。如果有什么细节上的问题以及自身不明白的地方很欢迎大家来和我讨论,我一个小白也希望可以更深层次的掌握这一门语言嘿嘿,谢谢各位大佬的阅读!!!