C++ STL容器 常用操作大全
序列容器
顺序容器的元素排列次序与元素值无关,而是由元素添加到容器里的次序决定。包含:(forword_list,list,queue,priority_queue,stack,deque,vector,array(虽然他被归为序列容器,但是并不满足序列的所以要求!))。
- 序列的要求
X a(n,t) //声明一个名为a的有n个t组成的序列
X(n,t) //匿名序列(这里我们不做过多的解释)
X a(i,j) //声明一个名为a的序列,并且初始化[i,j)
的内容
X(i,j) //匿名序列
v.insert() //由于insert重载方法比较多
1.v.insert(p,t)//将t插到迭代器p的前面
2.v.insert(p,n,t)//将n个t插入迭代器p之前
3.v.insert(p,i.j)//将区间[i,j)的元素插入到迭代器p之前
v.erase(t,k)
1.v.erase(t,k)//删除[t, k)之间的元素
2.v.erase(p)//删除迭代器p指向的元素
v.chear===v.erase(begin(),end());
Vector
-
概述
动态数组,在内存中具有连续的储存空间,在堆上分配内存,支持快速随机访问,在中间插入和删除慢,但在末尾插入和删除快。一个vector的容量永远大于或等于其大小,一旦容量等于大小,便是满载,下次再有新增元素,整个vector容器就得另觅居所。因此,对vector的任何操作,一旦引起空间的重新配置,指向原vector的所有迭代器就都失效了。 -
定义和初始化
vector<int> v;//默认初始化 vector<int> v(v1);//用v1初始化v vector<int>v(v1.begin(),v1.end());//用v1初始化v vector<int> v(10);//定义一个大小为10的数组! vector<int> v(10,1)//定义个全为1而且长度为10的数组
-
方法
a.front() //返回第一个元素
a.back() //末尾元素
c.begin() 返回一个迭代器,它指向容器的第一个元素
c.end() 返回一个迭代器,它指向容器的最后一个元素的下一个位置
c.rbegin() //返回一个逆序迭代器,它指向容器的最后一个元素
c.rend() 返回一个逆序迭代器,它指向容器的第一个元素前面的位置
v,push_back() //增
v.insert() //插入
1、v.insert(p, t) //将t插到p的前面
2、v.insert(p, n, t) //将n个t插入p之前
3、v.insert(p, i, j) //将区间[i,j)的元素插入到p之前
v.pop_back();//删除最后一个元素
v.erase(t,k)
1、v.erase(t,k)//删除[t,k)之间的元素
2、v.erase(p)//删除p指向的元素
v.chear()==v.erase(begin(),end());//删除所有元素
- 遍历
//下标法
int length = v.size();
for(int i=0;i<length;i++)
{
cout<<v[i];
}
cout<<endl;
//迭代器法
vector<int>::const_iterator iterator = v.begin();
for(;iterator != v.end();iterator++)
{
cout<<*iterator;
}
-
时间复杂度
头部插入删除:O(N)尾部插入删除:O(1)
中间插入删除:O(N)
查找:O(N)
查找通过algorithm库中的find函数,其调用形式为
find(start,end,value)
返回值为对应的迭代器,若不存在则返回a.end()
`
deque
-
概述
deque是double ended queue的缩写,是一个动态数组,可以向两端发展(双向开口的连续线性空间),因此无论在头部或者尾部安插元素都十分迅速,在中间按插元素则比较费时,因为必须移动其他元素。
双端队列的元素被表示为一个分段数组,容器中的元素分段存放在一个个大小固定的数组中,此外,容器还需要维护一个存放这些数组首地址的索引数组。如下图所示:
初始化与定义已经在序列要求里面,而且方法与vector类似,只是多了push_front()(),pop_front(),这里不做过多的阐述。
-
时间复杂度分析
头部尾部插入删除:O(1)中间插入删除:O(N)
查找:O(N)
list
-
概述
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
List容器是一个双向链表。 -
特点
1)没有预留空间的习惯,所以每分配一个元素都会从内存中分配,每释放一个元素都会释放其占用的内存2)任何地方插入删除的效率都很高,不需要移动内存,也就不需要在移动过程中对每个元素进行构造和析构,常用来做随机插入和删除的容器
3)访问首尾元素最快
-
独有方法
void sort() //使用<运算符对链表进行排序,时间复杂O(NlogN)
void merge(list<T,Alloc>&x) //将x与调用链表合并,要求:两个链表必须要已经排好序!元素将保存在调用链表中,x为空,这个时间复杂度为线性!
void remove(const T &val)//删除val的所有实例
void splice(iterator pos,list<T,Alloc>x)//将链表x的内容加到pos的前面,时间复杂度为固定时间
//insert与splice的区别:insert将list对象的副本插入到目标区域中,而splice是将该对象直接移到目标地址。通俗地说前者是复制,粘贴。后者是剪切,粘贴。
1、void splice( iterator pos, list &lst );
2、void splice( iterator pos, list &lst, iterator del );
3、void splice( iterator pos, list &lst, iterator start, iterator end );
void unique() //去重,线性时间
-
时间复杂度分析
任何位置的插入删除:O(1)(假设告诉了你插入删除的位置,不需要你线查找再删除)查找:O(N)
序列容器适配器
包括stack、queue、priority_queue
- 都支持的操作
A a; //创建一个名为a的空适配器
关系运算符 ==、!=、<、<=、>、>=;这些运算符都返回底层容器的比较结果
a.empty()
a.size() //元素数目
swap(a, b)或a.swap(b) //交换a和b的内容,a和b必须有相同类型,底层类型也相同
stack
- 概述
stack是一种先进后出(First In Last Out,FILO)的数据结构。stack不提供遍历功能,也不提供迭代器。
- 方法
push(elem);//向栈顶添加元素
pop();//从栈顶移除第一个元素
top();//返回栈顶元素
queue
- 概述
queue所有元素的进出都必须符合”先进先出”的条件,只有queue的顶端元素,才有机会被外界取用。queue不提供遍历功能,也不提供迭代器。
- 方法
q.pop();//删除首元素,但不返回元素值
q.front();//返回首元素,但不删除
q.back();//返回尾元素
q.push(item);//在尾端添加一个item元素
q.emplace(arg);//在尾端添加一个由arg构造的元素
priority_queue(优先队列)
- 概述
与queue基本一样,但是他的最大元素被移动到队首(生活不总是公平对,队列也一样),内部区别在于底层结构不一样,他用的是vector,当然我们可以修改确定拿个元素放在队首的比较方式!
priority_queue<int> X //大根堆,默认初始化
priority_queue<int, vector<int>, greater<int>> x //小根堆,运用了预定义函数greater<int>!
- 方法
支持与queue一样的方法。
关联容器
set
- 概述
set由红黑树实现,其内部元素依照其值自动排序,每个元素只出现一次,不允许重复(红黑树是平衡二叉树的一种) - 特点
1)元素有序
2)无重复元素
3)插入删除操作的效率比序列容器高,因为对于关联容器来说,不需要做内存的拷贝和内存的移动
4)对于迭代器来说,不可以修改值 - 方法
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相等的上下限的两个迭代器。
- 时间复杂度分析
增删改查近似:O(log N)
multiset
- 概述
multiset和set相同,只不过它允许重复元素,也就是说multiset可包括多个数值相同的元素。这里不再做过多介绍。
map
- 概述
map由红黑树实现,其元素都是键值对,每个元素的键是排序的准则,每个键只能出现一次,不允许重复。 - 特点
1)元素为键值对形式,键和值可以是任意类型
2)因为key有序,所以可以通过二分对key进行快速查找
3)增加和删除结点对迭代器的影响很小,除了当前结点是迭代器指向的结点
4)对于迭代器来说,可以修改值,但是不能修改key - 方法
size();//返回容器中元素的数目
empty();//判断容器是否为空
map.insert(...); //往容器插入元素,返回pair<iterator,bool>
map<int, string> mapStu;
// 第一种 通过pair的方式插入对象
mapStu.insert(pair<int, string>(3, "小张"));
// 第二种 通过pair的方式插入对象
mapStu.inset(make_pair(-1, "校长"));
// 第三种 通过value_type的方式插入对象
mapStu.insert(map<int, string>::value_type(1, "小李"));
// 第四种 通过数组的方式插入值
mapStu[3] = "小刘";
mapStu[5] = "小王";
clear();//删除所有元素
erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg,end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(keyElem);//删除容器中key为keyElem的对组。
find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;/若不存在,返回map.end();
count(keyElem);//返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是1。对multimap来说,值可能大于1。
lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器。
- 时间复杂度分析
增删改查基本是O(log N)
multimap
- 概述
multimap和map相同,但允许重复元素,也就是说multimap可包含多个键值(key)相同的元素。这里不再做过多介绍。
补充
- list、map、set、unordered_map、unordered_set的迭代器不支持加减法,只支持++、–