目录
Vector
1.构造函数
#include <vector>
//直接通过数组创建一个vector
vector<int> vecA = {1, 2, 3, 4};
//复制迭代器区间内的元素到vector中
vector<int> vecB(vecA.begin(), vecA.end());
//复制另一个数组的元素到vector中
int Array[4] = {1, 2, 3, 4};
vector<int> vecC(Array, Array+4);
//复制构造函数
vector<int> vecD(vecA);
/*或vecD = vecA;*/
//创建一个vector,元素个数为3,且值均为6
vector<int> vecE(3, 6);
2.数据操作函数
#include <vector>
vector<int> vecA;
//向量中迭代器指向元素前增加一个元素x
vecA.insert(vecA.begin()+3, x);
/*insert函数有三种插入方法:
insert(pos_iterator,elem):向量中迭代器指向元素位置前增加一个元素elem
insert(pos_iterator,n,elem):向量中迭代器指向元素前增加n个相同的元素elem
insert(pos_iterator,first_iterator,last_iterator):
向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据*/
//删除向量中迭代器指向元素
vecA.erase(vecA.begin()+3);
//返回向量第i个元素(i=0开始)
cout<<vecA.at(i);
//设置向量中前4个元素的值为10(assgin函数是覆盖式的)
vecA.assign(4,10);
//向量中[first,last)中元素设置成当前向量元素
vecB.assign(vecA.begin()+3,vecA.end()-2);
//交换两个同类型向量的数据
vecB.swap(vecA);
//重新指定容器的长度为num,若容器变长,则用elem填充新位置
vecC.resize(num,elem);
3.判断函数
//判断向量是否为空,返回值为布尔类型
vecA.empty();
//返回向量中元素的个数
vecA.size();
//清空向量中所有元素
vecA.clear();
4.Vector迭代器的失效
动态数组在进行插入操作后,可能会触发容器的扩容,导致数组中的元素被重新存储到新的连续内存空间,迭代器失效。insert()函数的返回值即为指向所插入元素的迭代器,所以可以使用语句it = list.insert(it)来立即给失效的迭代器重新赋值。
同理,动态数组的元素删除后会使迭代器的指针变为野指针,所以需要给迭代器重新赋值,erase()函数的返回值即为删除元素下一个元素的迭代器,所以可以使用语句it = list.erase(it)来立即给失效的迭代器重新赋值。
List
List容器中大多函数和Vector容器相同,都有.begin()/.end()迭代器、数值操作函数、构造函数等,但由于双向链表的特殊结构,没有at函数与[ ]操作符,迭代器只能++逐一递增,但链表拥有反向迭代器:reverse_iterator。(vector也有)
1.头尾函数
#include <list>
list<int> li;
//头插法&尾插法&头删法&尾删法
li.push_front(8);
li.push_back();
li.pop_front();
li.pop_back();
//获取、修改头尾结点
li.front() = 1;
li.back() = 3;
2.反向迭代器
rbegin是倒数第一个,rend是倒数第一个的前一个。
使用.reverse();函数也能实现list容器的反转。
list<int> li = { 1,2,3,4,5,6 };
list<int>::reverse_iterator it;
for (it = li.rbegin(); it != li.rend(); it++) {
cout << *it << endl;
}
3.List迭代器的失效
由于链表的结点删除后会使迭代器的指针变为野指针,所以需要给迭代器重新赋值,erase()函数的返回值即为删除结点下一个结点的迭代器,所以可以使用语句it = list.erase(it)来立即给失效的迭代器重新赋值。
但是由于链表插入操作不会影响当前结点的空间,因此List容器的insert()函数并不会导致迭代器失效。
Deque
deque容器和vector容器基本一致,但拥有头元素操作函数:pop_front()函数和push_front()函数。deque容器在头部和尾部进行元素的添加和删除都是O(1),不像vector容器对头部进行操作的时间复杂度为O(n)。
Stack
stack容器的元素遵循先进后出的原则,容器中的函数十分有限,且没有对应的迭代器。(栈不允许遍历)
1.构造函数
stack<int> A;
//利用构造函数将A容器中元素拷贝到B、C中
stack<int> B(A);
stack<int> C = A;
2.出栈、入栈、访问栈顶函数
#include <iostream>
#include <stack>
using namespace std;
int main()
{
stack<int> stk;
stk.push(1);
stk.push(2);
stk.push(3);
stk.push(4);
//入栈操作
stk.pop();
//栈顶元素出栈
cout << stk.top() << endl;
//返回栈顶元素,结果为3
return 0;
}
3.判断函数
由于栈为空时调用pop函数会导致运行出错,需要判断栈是否已经为空。
stack<int> A;
//判断堆栈是否为空
A.empty();
//返回容器存储元素个数
A.size();
Queue
Queue容器的元素遵循先进后出的原则,队尾插入元素,队首取出元素。队列容器也没有对应的迭代器,无法进行遍历操作。
1.出队、入队、访问队首/队尾函数
#include <iostream>
#include <queue>
using namespace std;
int main()
{
queue<int> Q;
Q.push(1);
Q.push(2);
Q.push(3);
Q.push(4);
//在队尾插入元素
Q.pop();
//在队首删除元素
if(!Q.empty())//判断队列非空
cout << Q.front() << endl << Q.back() << endl;
//分别在首尾访问元素,结果为2和4
return 0;
}
2.其他函数
队列容器和栈容器一样,也有empty(),size()判断函数以及构造函数,也可以让stack.front()或back()充当左值,给队首或队尾元素重新赋值。
Set
Set集合的特点:元素有序、不重复、无索引;
MultiSet集合的特点:元素有序、可重复、无索引;
Set是一个集合容器,集合中的元素自动按顺序排列,因此不能指定插入位置。Set采用红黑树变体的数据结构实现,插入和删除操作效率高于Vector容器。不能直接修改集合中的元素值,必须删除指定元素后插入要替代的元素。
Set容器和之前的容器相似,也可以用拷贝构造函数以及swap()函数进行容器内元素的交换。
1.插入与遍历函数
#include <iostream>
#include <set>
using namespace std;
int main()
{
set<int> A;
A.insert(1);
A.insert(4);
A.insert(2);
A.insert(3);
A.insert(5);
A.insert(5);
A.insert(3);
//set容器默认为升序排序
set<int>::iterator it;
for (it = A.begin(); it != A.end(); it++) {
cout<<*it<<endl;
}
//遍历结果为1,2,3,4,5
return 0;
}
set容器默认为升序排序,可以使用反向迭代器从大到小遍历,或者使用set<int, greater<int>>构造容器。
2.删除函数
Set无法进行指定位置的插入;和Vector容器与List容器相似,Set容器在函数中传递迭代器的参数完成指定位置的删除。(函数参数中不能使用反向迭代器)
//清除所有元素
set.clear();
//删除迭代器所指向元素,返回下一个元素的迭代器
set.erase(pos_iterator);
//删除迭代器中值为elem的元素(不存在则返回false)
set.erase(elem);
//删除迭代器指向区间[first,last)间的数据
set.erase(first_iterator,last_iterator);
3.查找函数
#include <iostream>
#include <set>
using namespace std;
int main()
{
multiset<int> A;
A.insert(1);
A.insert(4);
A.insert(2);
A.insert(3);
A.insert(5);
A.insert(5);
A.insert(3);
/*1,2,3,3,4,5,5*/
cout << *A.find(3) << endl;
//find(elem)返回第一个指向elem的迭代器,结果为3
cout << A.count(3) << endl;
//count(elem)返回容器中elem的个数,结果为2
cout << *A.lower_bound(3) << endl;
//lower_bound(elem)返回第一个>=elem的迭代器,结果为3
cout << *A.upper_bound(3) << endl;
//upper_bound(elem)返回第一个>elem的迭代器,结果为4
pair<multiset<int>::iterator, multiset<int>::iterator> P = A.equal_range(3);
cout<< *(P.first) <<endl;
//.equal_range(elem)返回两个迭代器,分别是lower_bound(elem)和upper_bound(elem)的结果
//结果为3 4
return 0;
}
其中pair<T1,T2>为对组,可以同时存储两种类型的数据,使用.first/.second获取成员。
4.利用伪函数自定义排序规则
#include <iostream>
#include <set>
using namespace std;
class shishishi {
public :
bool operator()(int a, int b)const{//第一个空括号表示对函数()运算符的重载
//改成这行VS会报错:bool operator()(const int &a, const int &b) {
return a < b;
}
};
int main()
{
set<int,shishishi> A;
A.insert(1);
A.insert(4);
A.insert(2);
A.insert(3);
A.insert(5);
A.insert(5);
A.insert(3);
set<int>::iterator it;
for (it = A.begin(); it != A.end(); it++) {
cout<<*it<<endl;
}
return 0;
}
Map
map/multimap容器的默认构造方式:map<T1,T2> mapA;
T1\T2可以为不同类型,分别代表key和value。
1.插入、遍历函数
#include <iostream>
#include <map>
using namespace std;
int main()
{
map <int, string> mapA;
//对组插入
mapA.insert(pair<int, string>(1, "sans"));
/* 也可以单独声明队组:pair<int, string> p(1, "sans");
mapA.insert(p);*/
//value_type插入,value_type本质上是map类的内部类
mapA.insert(map <int, string>::value_type(2, "frisk"));
//[]运算符重载插入,若map中已经有键,则修改对应值
mapA[3]= "chara";
map<int, string>::iterator it;
for (it = mapA.begin(); it != mapA.end(); it++) {
pair<int, string> P = *it;//利用对组存储迭代器所指的键值对,再分别提取
int key = P.first;
string value = P.second;
cout << key << " " << value << endl;
}
/*结果为:1 sans
2 frisk
3 chara*/
return 0;
}
注:使用insert函数插入键值对,若map中已存在相同的键,则不会改变原有的数据,也无法插入新的数据,而使用[ ]插入,若map中已经有键,则修改对应值。
2.获取键对应的值
#include <iostream>
#include <map>
using namespace std;
int main(){
map<int,string> mapA;
mapA[1] = "sans";
mapA[2] = "frisk";
mapA[3] = "chara";
cout << mapA[2] << endl;
//结果为frisk,不推荐使用,因为如果写mapA[4]会额外创建新的键值对
cout << (*mapA.find(3)).second << endl;
//结果为chara
//find()函数返回指向相应pair的迭代器,键值对用Pair存储,可以用.second获取。注意要用括号括起来
return 0;
}