C++ STL容器整理
序列式容器
vector的用法
vector是向量类型,它可以容纳许多类型的数据,如若干个整数,所以称其为容器。vector是C++STL的一个重要成员,使用它时需要包含头文件:
#include < vector >
一、vector(向量)类模板
vector是定义于名称空间(namespace)std内的模板。
其原型为:
template <class T, class Allocator = allocator<T>> class vector;
vector的迭代器是随机存取迭代器,对任何一个STL算法均奏效。 尤其在容器末端或删除元素时,vector性能相当好。
二、vector的初始化:可以有五种方式,举例如下:
(1) vector< int> a(10);
//定义了10个整形元素的向量 (尖括号中为元素类型名,它可以是任何合法的数据类型), 但没有给出初值,其初值是垃圾值。
(2)vector< int> a(10, 1);
//定义了10个整形元素的向量,且给出每个元素的初值为1
(3)vector< int> a(b);
//用b向量来创建a向量,整体复制性赋值
(4)vector< int> a(b.begin(), b.begin + 3);
//定义了a值为b中第0个到第2个(共3个)元素
(5)int b[7] = {1, 2, 3, 4, 5, 9, 8};
vector< int> a(b, b + 7);
//从数组中获得初值
三、vector的基本应用函数
(1)a.assign(b.begin(), b.begin()+3);
//b为向量,将b的0~2个元素构成的向量赋给a
(2)a.assign(4,2);
//a只含4个元素,且每个元素为2
(3)a.back();
//返回a的最后一个元素
(4)a.front();
//返回a的第一个元素
(5)a[i];
//返回a的第i个元素,当且仅当a[i]存在
(6)a.clear();
//清空a中的元素
(7)a.empty();
//判断a是否为空,空则返回ture,不空则返回false
(8)a.pop_back();
//删除a向量的最后一个元素
(9)a.erase(a.begin()+1,a.begin()+3);
//删除a中第1个 (从第0个算起) 到第2个元素,也就是说删除的元素从a.begin()+1算起(包括它)一直到a.begin()+ 3(不包括它)
(10)a.push_back(5);
//在a的最后一个向量后插入一个元素,其值为5
(11)a.insert(a.begin()+1,5);
//在a的第1个元素(从第0个算起)的位置插入数值5,如a为1,2,3,4,插入元素后为1,5,2,3,4
(12)a.insert(a.begin()+1,3,5);
//在a的第1个元素(从第0个算起)的位置插入3个数,其值都为5,如a为1,2,3, 插入后元素为1,5,5,5,2,3
(13)a.insert(a.begin()+1,b+3,b+6);
//b为数组,在a的第1个元素(从第0个算起)的位置插入b的第3个元素到第5个元素(不包括b+6),如a为1, 2, 3,b为1,2,3,4,5,6,7,插入元素后为1,4,5,6,2,3
(14)a.size();
//返回a中元素的个数;
(15)a.capacity();
//返回a在内存中总共可以容纳的元素个数
(16)a.resize(10);
//将a的现有元素个数调至10个,多则删,少则补,其值随机
(17)a.resize(10,2);
//将a的现有元素个数调至10个,多则删,少则补,其值为2
(18)a.reserve(100);
//将a的容量(capacity)扩充至100,也就是说现在测试a.capacity();的时候返回值是100.这种操作只有在需要给a添加大量数据的时候才 显得有意义,因为这将避免内存多次容量扩充操作(当a的容量不足时电脑会自动扩容,当然这必然降低性能)
(19)a.swap(b);
//b为向量,将a中的元素和b中的元素进行整体性交换
(20)a==b;
//b为向量,向量的比较操作还有!=,>=,<=,>,<
四、顺序访问vector的几种方式
(1)向向量a中添加元素
1、
vector<int> a;
for(int i = 0; i < 10; i++)
a.push_back(i);
2、也可以从数组中选择元素向向量中添加
int a[6] = {1, 2, 3, 4, 5, 6};
vector<int> b;
for(int i =0; i <= 4; i++)
b.push_back(a[i]);
3、也可以从现有向量中选择元素向向量中添加
int a[6] = {1, 2, 3, 4, 5, 6};
vector<int> b;
vector<int> c(a, a + 4);
for(vector<int>::iterator it = c.begin(); it != c.end(); it++)
b.push_back(*it);
4、[误区]
vector<int> a;
for(int i = 0; i < 10; i++)
a[i] = i;
//这中做法以及类似的做法都是错误的。下标只能用于获取已存在的元素,而现在的a[i]还是空的对象
(2)从向量中读取元素
1、通过下标方式读取
int a[6] = {1, 2, 3, 4, 5, 6};
vector<int > b(a, a + 4);
for(int i = 0; i < b.size() - 1; i++)
cout << b[i] << " ";
2、通过遍历器方式读取
int a[6] = {1, 2, 3, 4, 5, 6};
vector<int > b(a, a + 4);
for(vector<int>::iterator it = b.begin(); it != b.end(); it++)
cout << *it << " ";
五、几种重要的算法,使用时需要包含头文件:
#include < algorithm>
(1)sort(a.begin(),a.end()); //对a中的从a. begin(包括它)到a.end()(不包括它)的元素进行从小到大排列
(2)reverse(a.begin(),a.end()); //对a中的从a. begin()(包括它)到a.end()(不包括它)的元素倒置,但不排列,如a中元素为1,3,2,4,倒置后为4,2,3,1
(3)copy(a.begin(),a.end(),b.begin()+1); //把a中的从a. begin()(包括它)到a.end()(不包括它)的元素复制到b中,从b.begin()+1的位置(包括它)开始复制,覆盖掉原有元素
(4)find(a.begin(),a.end(),10); //在a中的从a. begin()(包括它)到a.end()(不包括它)的元素中查找10,若存在返回其在向量中的位置
list的用法
List将元素按顺序储存在链表中,与向量(vector)相比,它允许快速的插入和删除,但是随机访问却比较慢
使用它时需要包含list头文件:
#include < list>
一、list是定义于名称空间(namespace)std内的模板。
其原型为:
template <class T, class Allocator = allocator<T>> class list;
二、list的初始化:可以有五种方式,举例如下:
(1)list <int> listname;
//定义了一个list对象(尖括号中为元素类型名,它可以是任何合法的数据类型),但没有给出初值。
(2)list <int> listname(size);
//创建了一个初始大小为size的list对象,没初始值。
(3)list <int> listname(size, value);
//创建了一个初始大小为size,每个元素的初始值为value的对象。
(4)list <int> listnames(elselist);
//利用复制构造函数从现有的list中创建新的list对象。
(5)list <int> listname(first, last);
//创建1个list对象,并从其他list对象中复制由迭代器指定范围的多个元素。
三、list的基本应用函数
(1)a.assign();
//给list赋值
(2)a.back() ;
//返回最后一个元素
(3)a.begin();
//返回指向第一个元素的迭代器
(4)a.clear();
// 删除所有元素
(5)a.empty();
//如果list是空的则返回true
(6)a.end();
//返回末尾的迭代器
(7)a.erase();
//删除一个元素
(8)a.front();
//返回第一个元素
(9)a.insert();
//插入一个元素到list中
(10)a.max_size();
//返回list能容纳的最大元素数量
(11)a.merge(b);
//合并两个list
(12)a.pop_back();
//删除最后一个元素
(13)a.pop_front();
//删除第一个元素
(14)a.push_back();
//在list的末尾添加一个元素
(15)a.push_front();
//在list的头部添加一个元素
(16)a.rbegin();
//返回指向第一个元素的逆向迭代器
(17)a.remove(begin, end, value);
//删除begin开始到end中所有与value相等的元素
(18)a.remove_if(begin, end, cmp);
//删除begin开始到end中所有满足条件的元素
(19)a.rend();
//指向list末尾的逆向迭代器
(20)a.resize();
//改变list的大小
(21)a.reverse();
//把list的元素倒转
(22)a.size();
//返回list中的元素个数
(23)a.sort();
//给list排序
(24)a.splice(b);
//合并两个list
(25)a.splice(b,iterator first);
//将b中的某个元素(first指向的元素)插入it的后面
(26)a.splice(b, begin, end);
//将b中某个范围(begin,end)内的元素插入在it后面。
(25)swap(a, b);
//交换两个list
(26)a.unique();
//删除list中重复的元素
四、list的几种访问方式
(1)、向list中添加元素
1、向list头部插入新元素
list <int> listnames;
listname.push_front(a);//在容器中的头部插入新元素a
2、向list尾部插入新元素
list <int> listname;
listname.push_back(a); //在容器中的尾部插入新元素a
(2)、删除list中的元素
1、删除list头部的元素
list <int> listnames;
listname.push_front(a);
listname.push_front(b);
listname.push_front(c);
listname.pop_front(d);//将头部的元素返回至d,并删除头部元素
2、删除list尾部的元素
list <int> listnames;
listname.push_front(a);
listname.push_front(b);
listname.push_front(c);
listname.pop_back(d);//将尾部的元素返回至d,并删除尾部元素
deque(双端队列)的用法
deque模板类提供了对序列随机访问的功能,可以实现在序列两端快速插入和删除操作的功能,在需要时修改自身大小。deque可以完成标准C++数据结构中队列的所有功能。
使用它时需要包含deque头文件:
#include <deque>
一、头文件中,deque类模板的定义如下:
template <class T, class Allocator = allocator<T>> class deque;
二、deque的初始化:可以有五种方式,举例如下:
(1)deque <typename T> name;
//创建容纳类型T的空deque容器对象
(2)deque <typename T> name(size);
//创建初始大小为size的deque对象
(3)deque <typename T> name(size, value);
//创建初始大小为size,每个元素初始值value的deque对象
(4)deque <typename T> name(elsedeque);
//用复制构造函数从现有的deque型容器elsedeque中创建新的deque容器对象
(5)deque <typename T> name(elsedeque.first(), elsedeque.end());
//使用迭代器创建deque容器对象
三、deque的基本应用函数
(1)c.at(index);
//返回索引下标index所指的数据(从0开始)
(2)c.front();
//返回第一个数据
(3)c.back();
//返回最后一个数据
(4)c.begin();
//返回指向第一个数据的迭代器
(5)c.end();
//返回指向最后一个数据的下一个位置的迭代器
(6)c.regin();
//返回逆向队列的第一个数据
(7)c.rend();
//返回指向逆向队列的最后一个数据的下一个位置的迭代器
(8)c.clear();
//销毁所有数据,释放内存
(9)c.empty();
//判断容器是否为空
(10)c.resize(n);
//deque队列的长度置为n,只保留队列前n个数
(11)c.size();
//返回容器中实际数据的个数
(12)swap(c1, c2);
//将c1和c2元素互换
四、deque的几种访问方式
(1)、向deque中添加元素
1、在尾部添加一个数据
deque <int> c;
c.push_back(num); //在容器尾部添加一个数据num
2、在头部添加一个数据
deque <int> c;
c.push_front(num); //在容器头部添加一个数据num
3、在pos前添加一个数据
deque <int> c;
c.insert(pos, num); //在该pos位置的数前面插入一个num
4、在pos前添加n个相同数据
deque <int> c;
c.insert(pos, n, num); //在该pos位置的数前面插入n个num
5、在pos前添加一个区间的数据
deque <int> c;
c.insert(pos, beg, end); //在该pos位置的数前插入在[beg,end)区间的数据
(2)、删除deque中的元素
1、删除最后一个元素
deque <int> c;
c.push_front(1);
c.push_front(2);
c.pop_back();//删除最后一个数据
2、删除头部数据
deque <int> c;
c.push_front(1);
c.push_front(2);
c.pop_front();//删除头部数据
3、删除pos位置的数据
deque <int> c;
c.push_front(1);
c.push_front(2);
c.erase(pos); //删除pos位置的数据
4、删除[beg, end)
deque <int> c;
c.push_front(1);
c.push_front(2);
c.erase(beg, end);//删除[beg, end)区间的数据
关联式容器
set的用法
set型容器能顺序存储一组数值,这些数值既充当存储的数据,又充当数据的键值。该集合更像一个有序链表,其中的元素以升序顺序存储。
要使用set,则必须要包含set头文件
#include <set>
一、头文件中,set类模板的定义如下:
template <c;assKey, class Traits = less<Key>, class Allocator = allocator<Key>> class set;
二、set的初始化:
set<int > s;
//创建一个空的set对象
三、set的基本应用函数
(1)s.begin();
//返回指向第一个元素的迭代器
(2)s.clear();
//清除所有元素
(3)s.count();
//返回某个值元素的个数
(4)s.empty();
//如果集合为空,返回true
(5)s.end();
//返回指向最后一个元素的迭代器
(6)s.erase();
//删除集合中的元素
(7)s.find();
//返回一个指向被查找到元素的迭代器
(8)s.insert();
//在集合中插入元素
(9)s.lower_bound()
//返回指向大于(或等于)某值的第一个元素的迭代器
(10)s.key_comp();
//返回一个用于元素间值比较的函数
(11)s.max_size();
返回集合能容纳的元素的最大限值
(12)s.rbegin();
//返回指向集合中最后一个元素的反向迭代器
(13)s.rend();
//返回指向集合中第一个元素的反向迭代器
(14)s.size();
//集合中元素的数目
map的用法
map型容器是(键-值)对的集合。map型容器通常可理解为关联数组,可使用键作为下标来获取对应的值,类似于内置数组类型。在STL中,要使用map,则必须要包含map头文件:
#include <map>
一、头文件中,set类模板的定义如下:
template <class Key, class T, class Compare = less <Key>, class Allocator = allocator <pair<const Key, T>>> class map;
二、map的初始化:可以又三种方式,举例如下:
(1)map<k, v> m;
//创建一个名为m的空map对象,其键和值得类型分别为k和v
(2)map<k, v> m(m1);
//创建m1的副本m,m与m1必须又相同的键类型和值类型
(3)map<k, v> m(b, e);
//创建map类型的对象m,存储迭代器b和e标记的范围内所有元素的副本。元素的类型必须能转换成pair<const k, v>
三、map的基本应用函数
(1)m.begin();
//返回指向map头部的迭代器
(2)m.clear();
//删除所有元素
(3)m.count();
//返回指定元素出现的次数
(4)m.empty();
//如果map为空则返回true
(5)m.end();
//返回指向map末尾的迭代器
(6)m.erase();
//删除一个元素
(7)m.find();
//查找一个元素
(8)m.insert();
//插入元素
(9)m.key_comp();
//返回比较元素key的函数
(10)m.lower_bound();
//返回键值>=给定元素的第一个位置
(11)m.max_size();
//返回可以容纳的最大元素个数
(12)m.rbegin();
//返回一个指向map尾部的逆向迭代器
(13)m.rend();
//返回一个指向map头部的逆向迭代器
(14)m.size();
//返回map中元素的个数
(15)m.upper_bound();
//返回键值>给定元素的第一个位置
特殊容器用法
stack的用法
stack类可以实例化一个栈容器(后进先出,LIFO)或栈对象。在STL中,要使用stack,则必须要包含stack头文件:
#include <stack>
一、头文件中,stack类模板的定义如下:
namesapce std{template <class T, class Container = deque<T>> class stack; }
二、stack的初始化:可以有两种方式,举例如下:
(1)stack<int> s;
//创建一个空的stack对象。
(2)stack <int, list<int>> s1;
satck<int , list<int>> s2(s1);
//创建一个以双向链表为底层容器的空栈对象s2
三、stack的基本应用函数
(1)a.push(b);
//将元素b压到栈顶
(2)a.pop();
//将栈顶元素弹出
(3)b = a.top();
//读取栈顶元素,并赋值给b
(4)a.size();
//返回栈内元素个数
(5)a.empty();
//判断栈是否为空,栈空返回true,栈非空返回false
四、stack的几种访问方式
(1)、向栈中添加元素
stack <int> a;
a.push(b); 将元素b压到栈顶
(2)、删除栈顶元素
stack<int> a;
a.push(b);
a.push(c);
while(!a.empty()) //判断栈是否为空
a.pop(); //将栈顶元素删除
堆栈是一种应用非常广泛的数据结构。C++STL将这种数据结构和它若干受限制操作用泛型类stack容器封装起来,包括堆栈初始化、元素入栈、取栈顶元素、元素出栈、判断堆栈是否非空和取得当前堆栈大小等,应用起来十分容易。
queue的用法
queue类模板可以实例化队列容器(先进先出, FIFO)。queue是双端口的,元素压入时是从一端,元素移除时是从另一端。通俗来讲,queue是典型的数据缓冲区结构。在STL中,要使用queue,则必须要包含queue头文件:
#include <queue>
一、头文件中,queue类模板的定义如下:
namesapce std{template <class T, class Container = deque<T>> class queue; }
二、queue的初始化
queue<int> a;
//创建一个int型的队列(尖括号中为元素类型名,它可以是任何合法的数据类型)
三、queue的基本应用函数
(1)a.back();
//返回一个引用,返回队列的最后一个元素。
(2)a.empty();
//函数返回真(true)如果队列为空,否则返回假(false)。
(3)a.front();
//返回队列第一个元素的引用。
(4)a.pop();
//函数删除队列的一个元素
(5)a.push();
//在末尾加入一个元素
(6)a.size();
//返回队列中元素的个数