目录
SDL标准模板库分为三类:
放入普通变量
放入普通类
使用指针类对象
详解三类标准库
容器:
vector容器:
访问方式:
vector:resize:改变容器大小和内存(删除值)
vector:pop_back:尾部删除值
vector:erase:指定位置值的删除
vector:iterator
vector:insert:指定位置值的插入
deque 容器
list容器
set&multise容器
map&multimap容器
queue容器(先进先出)
priority_queue
stack容器(后进先出)
algorithm(算法):对数据进行处理(解决问题) 步骤的有限集合
container(容器):用来管理一组数据元素
iterator(迭代器):可遍历 STL 容器内全部或部分元素”的对象
#include
//算法
#include//容器
#include//迭代器
容器和算法通过迭代器可以进行无缝地连接 。在 STL 中几乎所有的代码都采用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会[STL 被组织为下面的 13 个头文 件:、 、 、 、 、 ]、
//使用标准库三类
void test1() {
vector v1;//指定容器放的int型数据
//放入1,2,3,4,3,3
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(3);
v1.push_back(3);
//使用容器遍历
cout << "使用容器遍历" << endl;
for (int i = 0; i < v1.size(); i++){
cout << v1[i] <<" ";
}
cout << endl;
//使用迭代器进行输出
cout << "使用迭代器进行输出" << endl;
for (vector::iterator it = v1.begin(); it !=v1.end() ; it++){
//迭代器是一个特殊的指针,指向第一个元素,到最后一个元素的下一位
cout << *it <<" ";//对迭代器指针进行解引
}
cout << endl;
//使用算法计算容器中3的数量
cout << "使用算法计算容器中3的数量" << endl;
int countn = count(v1.begin(), v1.end(), 3);
cout << countn << endl;
}
这里调用了三次拷贝构造函数,
Man man1("小滕",22);
Man man2("文博波", 24);
v1.push_back(man1);
v1.push_back(man2);第一次,将对象man放入vector的时候会进行拷贝一次,
在将man1 放入vector中的时候这时候vector会进行扩容,扩容之后会将原本数组中的man拷贝一次,man1也会拷贝一次
class Man {
public:
Man(const char* name, int age) {
this->age = age;
strcpy_s(this->name, 64, name);
};
Man(const Man& man) {
this->age = man.age;
strcpy_s(this->name, 64, man.name);
cout <<"调用: " << __FUNCTION__ << endl;
}
public:
char name[64];
//string name;和string *name;
int age;
};
void test2() {
vector v1;
Man man1("小滕",22);
Man man2("文博波", 24);
v1.push_back(man1);
v1.push_back(man2);
cout << v1.size() << endl;
//使用容器遍历
cout << "使用容器遍历" << endl;
for (int i = 0; i < v1.size(); i++) {
cout << v1[i].name<<": "<::iterator it = v1.begin(); it != v1.end(); it++) {
//迭代器是一个特殊的指针,指向第一个元素,到最后一个元素的下一位
cout << (*it).name<<": "<<(*it).age << " ";//对迭代器指针进行解引
}
}
使用容器的push_back放对象的时候会多次执行拷贝函数,不安全,C11提供了一个接口用于解决这种情况 emplace_back
Man man("小滕", 22);
Man man1("文博波", 24);
v1.emplace_back("小滕", 22);
v1.emplace_back("文博波", 24);这里是直接调用带参的构造函数,但是在vector进行扩容的还是会将原本在数组中的进行拷贝一次
//当容器存放的是类指针的时候
void test3() {
vector v1;
Man man1("小滕", 22);
Man man2("文博波", 24);
v1.push_back(&man1);
v1.push_back(&man2);
//使用迭代器进行输出
cout << "使用迭代器进行输出" << endl;
for (vector::iterator it = v1.begin(); it != v1.end(); it++) {
//迭代器是一个特殊的指针,指向第一个元素,到最后一个元素的下一位
cout << (**it).name << ": " << (**it).age << " ";//对迭代器指针进行解引
}
}
容器部分主要有由
, , ,
,
赋值:push_back,assign(1),下标[],at(),front,back,,empty()
删除:clear(),pop_back,,resize(1),erase,
插入insert()//使用迭代器,
inverse-iterator;逆转输出
vector 是将元素置于一个 动态数组 中加以管理的容器。vector 可以随机存取元素 , 支持索引值直接存取, 用 [] 操作符或 at() 方法对元素进行操作
vector 尾部添加或移除元素非常快速。但是在中部或头部插入元素或移除元素比较费时
下标[] at() --->需要注意越界
接口:front()和back()
cout << "未修改之前的v1的值:";
for (int i = 0; i < v1.size(); i++){
cout << v1[i] << " ";
}
cout << endl;
cout << "使用[]修改第二个元素为1" << endl;
v1[1] = 1;
cout << "使用at()修改第三个元素为10" << endl;
v1.at(2) = 10;
cout << "使用front()修改第一个元素为8" << endl;
v1.front() = 8;
cout << "使用back()修改最后一个元素为12" << endl;
v1.back() = 12;
cout << "未修改之后的v1的值:";
for (int i = 0; i < v1.size(); i++) {
cout << v1[i] << " ";
}
//默认构造函数
vectorv1; //一个存放 int 的 vector 容器vectorv2; //一个存放 float 的 vector 容器vectorv2; //一个存放 student 的 vector 容器
//vector默认构造.元素个数为0,内存为0
vector v1;
//vector v2;
cout << "v1的大小:" << v1.size() << endl;
cout << "v1的内存大小:" << v1.capacity() << endl;
//当时用vector默认构造函数的时候,不能直接通过下标去访问,
//v1[0] = 1;
v1.push_back(1);
//尾部插入一个元素之后:
cout << "尾部插入一个元素之后:" << endl;
cout << "v1的大小:" << v1.size() << endl;
cout << "v1的内存大小:" << v1.capacity() << endl;
cout << "尾部插入五个元素之后:" << endl;
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
//当插入个数达到一定的量的时候,vector就会预选分配一个内存空间,加快放入速率
cout << "v1的大小:" << v1.size() << endl;
cout << "v1的内存大小:" << v1.capacity() << endl;
// 带参构造函数vector(beg,end);//构造函数将 [beg, end)区间中的元素拷贝给本身 。注意该区间是左闭右开的区间vector(n,elem);//构造函数将 n 个 elem 拷贝给本身vector(const vector &v1);//拷贝构造函数
//有参的默认构造函数
//vector v2(10, 0);//分配一个长度为10,元素为0的空间
vector v2(10, 6);//分配一个长度为10,所有元素为6的空间
vector v3(v2.begin(), v2.begin() + 2); //带参的构造函数时左闭右开的形式
//v3[等于 ,小于 );
for (int i = 0; i < v2.size(); i++){
cout << v2[i] << " ";
}
cout << endl;
cout << "v2的大小:" << v2.size() << endl;
cout << "v2的内存大小:" << v2.capacity() << endl;
cout << "使用迭代器给v3赋值:" << endl;
for (int i = 0; i < v3.size(); i++) {
cout << v3[i] << " ";
}
cout << endl;
cout << "v3的大小:" << v3.size() << endl;
cout << "v3的内存大小:" << v3.capacity() << endl;
//使用asign重新赋值,大小变了,但是已经分配的容器并不会发生改变
cout << "使用asign重新赋值" << endl;
v2.assign(4, 8);//第一种玩法 改变原来 vector 中的元素个数和值
for (int i = 0; i < v2.size(); i++) {
cout << v2[i] << " ";
}
cout << endl;
cout << "v2的大小:" << v2.size() << endl;
cout << "v2的内存大小:" << v2.capacity() << endl;
cout << endl;
cout << "使用asign+迭代器重新赋值" << endl;
v2.assign(v3.begin(), v3.end());//第二种玩法,使用迭代器重新赋值
for (int i = 0; i < v2.size(); i++) {
cout << v2[i] << " ";
}
cout << endl;
cout << "v2的大小:" << v2.size() << endl;
cout << "v2的内存大小:" << v2.capacity() << endl;
超出的值直接删除,将大小变为指定值,没有超出则,默认值为0
和push_back是一对,pop_back是在尾部进行删除
cout << "未删除之前的v1的值:";
for (int i = 0; i < v1.size(); i++){
cout << v1[i] << " ";
}
cout << endl;
cout << "v1的大小:" << v1.size() << endl;
cout << "v1的内存大小:" << v1.capacity() << endl;
cout << "使用pop_back之后:" << endl;
v1.pop_back();
for (int i = 0; i < v1.size(); i++) {
cout << v1[i] << " ";
}
cout << endl;
cout << "v1的大小:" << v1.size() << endl;
cout << "v1的内存大小:" << v1.capacity() << endl;
cout << endl;
clear();将所有值都删除
erase()迭代器
cout << "之前的v1的值:";
for (int i = 0; i < v1.size(); i++){
cout << v1[i] << " ";
}
cout << endl;
cout << "使用erase删除第三个位置的值" << endl;
v1.erase(v1.begin() + 2);//返回的是一个迭代器,这个迭代器指向下一个元素
for (int i = 0; i < v1.size(); i++) {
cout << v1[i] << " ";
}
cout << "使用迭代器输出" << endl;
for (vector::iterator it = v1.begin(); it != v1.end();it++){
cout << *it << " ";
}
cout << endl;
cout << "使用使用逆转迭代器输出" << endl;
for (vector::reverse_iterator it = v1.rbegin(); it != v1.rend(); it++) {
cout << *it << " ";
}
cout << endl;
cout << "使用常量迭代器输出" << endl;
for (vector::const_iterator it = v1.cbegin(); it != v1.cend(); it++) {
cout << *it << " ";
}
vector.insert(pos,elem);// 在 pos 位置插入一个 elem 元素的拷贝,返回新数据的位置。vector.insert(pos,n,elem);// 在 pos 位置插入 n 个 elem 数据,无返回值。vector.insert(pos,beg,end);// 在 pos 位置插入 [beg,end) 区间的数据,无返回值
cout << "未插入之前的v1的值:";
for (int i = 0; i < v1.size(); i++){
cout << v1[i] << " ";
}
cout << endl;
cout << "使用insert在第三个位置2个插入12之后" << endl;
v1.insert(v1.begin() + 2,2 ,12);
for (int i = 0; i < v1.size(); i++) {
cout << v1[i] << " ";
}
特点:deque 在接口上和 vector 非常相似,在许多操作的地方可以直接替换。deque 可以随机存取元素(支持索引值直接存取,用 [] 操作符或 at() 方法)deque 头部和尾部添加或移除元素都非常快速 , 但是在中部安插元素或移除元素比较费时。
带参:
方式 1 :deque(beg,end); dequedeqIntB(deqIntA.begin(),deqIntA.end()); // 构造函数将 [beg, end) 区间中的元素拷贝给本身。方式 2 : deque(n,elem);// 构造函数将 n 个 elem 拷贝给本身。方式 3 : deque(const deque &deq); // 拷贝构造函数
deque 头部和末尾的添加移除操作:
deque.push_back(element); //容器尾部添加一个数据deque.push_front(element); //容器头部插入一个数据deque.pop_back(); //删除容器最后一个数据deque.pop_front(); //删除容器第一个数据
deque 的数据存取
第一 使用下标操作 deqIntA[0] = 100;
第二 使用 at 方法 如 : deqIntA.at(2) = 100;第三 接口返回的引用 deqIntA.front() 和 deqIntA.back()deque 的赋值
deque.assign(beg,end); //将 [beg, end) 区间中的数据拷贝赋值给本身。注意该区间是左闭右开的区间。deque.assign(n,elem); //将 n 个 elem 拷贝赋值给本身。deque& operator=(const deque &deq); //重载等号操作符deque.swap(deq); // 将 deque 与本身的元素互换
deque 与迭代器deque.begin(); // 返回容器中第一个元素的迭代器。deque.end(); //返回容器中最后一个元素之后的迭代器。deque.rbegin(); // 返回容器中倒数第一个元素的迭代器。deque.rend(); //返回容器中倒数最后一个元素之后的迭代器。deque.cbegin(); // 返回容器中第一个元素的常量迭代器。deque.cend(); //返回容器中最后一个元素之后的常量迭代器。
//普通迭代器
for(deque::iterator it = deqIntA.begin(); it!=deqIntA.end(); ++it){
(*it)++; //*it++ (*it)++
cout<<*it;
cout<<" ";
}
//常量迭代器
deque::const_iterator cit = deqIntA.cbegin();
for( ; cit!=deqIntA.cend(); cit++){
cout<<*cit;
cout<<" ";
}
//逆转的迭代器
for(deque::reverse_iterator rit=deqIntA.rbegin(); rit!=deqIntA.rend();++rit){
cout<<*rit;
cout<<" ";
}
deque 的大小deque.size(); //返回容器中元素的个数deque.empty(); //判断容器是否为空deque.resize(num); //重新指定容器的长度为 num ,若容器变长,则以默认值 0 填充新位置。如果容器变短,则末尾超出容器长度的元 素被删除。deque.resize(num, elem); //重新指定容器的长度为 num ,若容器变长,则以 elem 值填充新位置。如果容器变短,则末尾超出容器长度的元素 被删除。
deque 的删除
deque.clear(); //移除容器的所有数据deque.erase(beg,end); //删除 [beg,end) 区间的数据,返回下一个数据的位置。deque.erase(pos); //删除 pos 位置的数据,返回下一个数据的位置。
deque 的插入deque.insert(pos,elem); //在 pos 位置插入一个 elem 元素的拷贝,返回新数据的位置。deque.insert(pos,n,elem); //在 pos 位置插入 n 个 elem 数据,无返回值。deque.insert(pos,beg,end); //在 pos 位置插入 [beg,end) 区间的数据,无返回值
List 特点:
list 不可以随机存取元素,所以不支持 at.(position) 函数与 [] 操作符。可以对其迭代器执行 ++ ,但是 不能 这样操作迭代器 :it+3使用时包含 #include
List不存在capacity(),不纯在提前分配空间,按需分配,不浪费
list 对象的带参数构造方式一:list(beg,end);//将 [beg, end) 区间中的元素拷贝给本身。方式二:list(n,elem); //构造函数将 n 个 elem 拷贝给本身。方式三:list(const list &lst); // 拷贝构造函数
list 头尾的添加移除操作list.push_back(elem); //在容器尾部加入一个元素list.pop_back(); //删除容器中最后一个元素list.push_front(elem); //在容器开头插入一个元素list.pop_front(); //从容器开头移除第一个元素
list 的数据存取list.front(); //返回第一个元素。list.back(); //返回最后一个元素。不存在下标和at()读取list 的赋值list.assign(beg,end); //将 [beg, end) 区间中的数据拷贝赋值给本身。list.assign(n,elem); //将 n 个 elem 拷贝赋值给本身。list& operator=(const list &lst); //重载等号操作符。list.swap(lst); // 将 lst 与本身的元素互换。
list 与迭代器
list.begin(); //返回容器中第一个元素的迭代器。
list.end(); //返回容器中最后一个元素之后的迭代器。list.rbegin(); //返回容器中倒数第一个元素的迭代器。list.rend(); //返回容器中倒数最后一个元素的后面的迭代器。list.cbegin(); //返回容器中第一个元素的常量迭代器。list.cend(); //返回容器中最后一个元素之后的常量迭代器。
list 的大小
ist.size(); //返回容器中元素的个数list.empty(); //判断容器是否为空list.resize(num); //重新指定容器的长度为 num ,若容器变长,则以默认值 0 填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。list.resize(num, elem); //重新指定容器的长度为 num ,若容器变长,则以 elem 值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
list 的插入list.insert(pos,elem); //在 pos 位置插入一个 elem 元素的拷贝,返回新数据 的位置。list.insert(pos,n,elem); //在 pos 位置插入 n 个 elem 数据,无返回值。list.insert(pos,beg,end); //在 pos 位置插入 [beg,end) 区间的数据,无返回值
list 的删除
list.clear(); //移除容器的所有数据list.erase(beg,end); // 删除 [beg,end) 区间的数据,返回下一个数据的位置。list.erase(pos); //删除 pos 位置的数据,返回下一个数据的位置。lst.remove(elem); //删除容器中所有与 elem 值匹配的元素。
list 的反序排列list.reverse(); //反转链表,比如 list 包含 1, 2, 3, 4, 5 五个元素,运行此方 法后,list 就包含 5, 4, 3, 2, 1 元素。
set 和 multiset 是一个集合容器,其中 set 所包含的元素是唯一的,集合中的元素按一定的顺序排列。set 采用红黑树变体的数据结构实现,红黑树属于平衡二叉树。在插入操作和删除操作上比 vector 快。在 n 个数中查找目标数的效率是 log2n
红黑树的定义:节点是红色或黑色;根节点是黑色;所有叶子节点都是黑色节点(NULL) ;每个 红色节点必须有两个黑色的子节点 。 ( 从每个叶子到根的所有路径上不能有两个连续的红色节点。 )从 任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点
Set 和 multiset 特点set 中元素插入过程是 按排序规则插入,所以 不能指定插入位置 。set 不可以直接存取元素。(不可以使用 at.(pos) 与 [] 操作符)。multiset 与 set 的区别:set 支持唯一键值,每个元素值只能出现一次;而 multiset 中 同一值可以出现多次 。不可以直接修改 set 或 multiset 容器中的元素值 ,因为该类容器是自动排序的。 如果希望修改一个元素值 ,必须先删除原有的元素,再插入新的元素头文件 #include
set setInt;
multiset mulInt;
//不能指定插入,只能按照顺序插入
cout << "使用set进行顺序赋值," << endl;
for (int i = 0; i < 10; i++){
setInt.insert(100 - i);
}
//不能插入重复的值
setInt.insert(8);
for (set::iterator it = setInt.begin(); it != setInt.end(); it++){
cout << *it << " ";
}
cout << endl;
cout << "使用multset进行顺序赋值," << endl;
for (int i = 0; i < 10; i++) {
mulInt.insert(100 - i);
}
//可以插入重复的值
mulInt.insert(99);
for (multiset::iterator it = mulInt.begin(); it != mulInt.end(); it++) {
cout << *it << " ";
}
Set/multiset 对象的带参构造函数
set(beg,end); //将 [beg, end) 区间中的元素拷贝给本身。set(const set &s); //拷贝构造函数。multiset(beg,end); //将 [beg, end) 区间中的元素拷贝给本身。multiset(const multiset &s); //拷贝构造函数。
set 对象的拷贝构造与赋值set(const set &st); //拷贝构造函数set& operator=(const set &st); //重载等号操作符set.swap(st); //交换两个集合容器
仿函数(函数对象)functor 的用法
尽管函数指针被广泛用于实现函数回调,但 C++ 还提供了一个重要的实现回调函数的方法,那就是函数对象。functor,翻译成函数对象,伪函数, 它是是重载了“()”操作符的普通类对象 。从语法上讲,它与普通函数行为类似。functional 头文件中包含的 greater<> 与 less<> 就是 函数对象。函数对象可以像函数一样直接使用
set
> setInt;
当排序的是类对象的时候,既可以通过重载operator><的比较运算符来实现排序,也可以通过set库提供的 重载operator()[仿函数]来实现
#include
#include
using namespace std;
class Student {
public:
Student(int age) {
this->age = age;
}
//自定义比较重载运算符
bool operator<(const Student& student) const{
cout << "调用了小于重载运算符" << endl;
return this->age < student.age;
}
bool operator>(const Student& student)const {
cout << "调用了小于重载运算符" << endl;
return this->age > student.age;
}
int getAge() const{
return age;
}
private:
int age;
};
//仿函数
class FunStudent {
public:
bool operator()(const Student& right, const Student& left)const {
cout << "调用了仿函数重载运算符" << endl;
bool temp = right.getAge() < left.getAge();
return temp;
}
private:
int ret;
};
int main(void) {
set stu;
stu.insert(Student(13));
stu.insert(Student(14));
stu.insert(Student(12));
stu.insert(Student(16));
cout << "重载比较运算符的结果"<::iterator it = stu.begin(); it != stu.end(); it++) {
cout << it->getAge() << " ";
}
cout << endl;
cout << "仿函数的结果" << endl;
set stu1;
stu1.insert(Student(13));
stu1.insert(Student(14));
stu1.insert(Student(12));
stu1.insert(Student(17));
for (set::iterator it = stu1.begin(); it != stu1.end(); it++) {
cout << it->getAge() << " ";
}
return 0;
}
set 的插入和 pair 的用法
pair 表示一个对组,它将两个值视为一个单元,把两个值捆绑在一起。pair用来存放的两个值的类型,可以不一样,也可以一样,如 T1 为 int , T2 为 float 。 T1,T2 也可以是自定义类。pair.first 是 pair 里面的第一个值,是 T1 类型。pair.second 是 pair 里面的第二个值,是 T2 类型setsetInt; for(int i=5; i>0; i--){pair::iterator, bool> ret = setInt.insert(i); if(ret.second){cout<<"插入 "< 成功! "< }else {cout<<"插入 "< 失败! "< }}
set 与迭代器set.insert(elem); //在容器中插入元素。set.begin(); //返回容器中第一个数据的迭代器。set.end(); //返回容器中最后一个数据之后的迭代器。set.rbegin(); //返回容器中倒数第一个元素的迭代器。set.rend(); //返回容器中倒数最后一个元素的后面的迭代器
set/multiset 的大小
set.size(); // 返回容器中元素的数目set.empty();// 判断容器是否为空注意事项: 它们没有 resize 方法
set/multiset 的删除
set.clear(); //清除所有元素set.erase(pos); //删除 pos 迭代器所指的元素,返回下一个元素的迭代器。set.erase(beg,end); //删除区间 [beg,end) 的所有元素,返回下一个元素的迭代器。set.erase(elem); //删除容器中值为 elem 的元素。如: setInt 是用 set声明的容器,假设它内部现已包含按顺序的 1, 2, 3, 4, 5, 6 元素。 set::iterator itBegin=setInt.begin(); ++ itBegin;set::iterator itEnd=setInt.begin(); ++ itEnd;++ itEnd;++ itEnd;setInt.erase(itBegin,itEnd); //此时容器 setInt 包含按顺序的 1, 4, 5, 6 四个元素。
set/multiset 的查找set.find(elem); //查找 elem 元素,返回指向 elem 元素的迭代器。find是否查找到元素可以通过迭代器遍历来判断元素是否存在set.count(elem); //返回容器中值为 elem 的元素个数。对 set 来说,要么是 0 ,要么是1 。对 multiset 来说,值可能大于 1 。set.lower_bound(elem); //返回第一个 >=elem 元素的迭代器。set.upper_bound(elem); // 返回第一个 >elem 元素的迭代器。set.equal_range(elem); //返回容器中与 elem 相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如 [beg,end) 。以上函数返回两个迭代器,而这两个迭代器被封装在 pair 中。
#include
#include
using namespace std;
int main(void) {
set setInt;
for (int i = 5; i > 0; i--) {
pair::iterator , bool> ret = setInt.insert(i);
if (ret.second)
{
cout << "插入" << *ret.first << "成功";
}
else {
cout << "插入" << i << "失败";
}
}
setInt.insert(6);
cout << endl;
cout << "遍历结果是:" << endl;
for (set::iterator it = setInt.begin();
it != setInt.end(); it++)
{
cout << *it << " ";
}
cout << endl;
//删除6
setInt.erase(6);
cout << "删除6遍历结果是:" << endl;
for (set::iterator it = setInt.begin();
it != setInt.end(); it++)
{
cout << *it << " ";
}
cout << endl;
cout << "单查找到5的位置是:" << " ";
set::iterator it = setInt.find(5);
cout << *it << endl;
cout << endl;
int n = setInt.count(1);
cout << n << endl;
set::iterator it1 = setInt.lower_bound(3);
set::iterator it2 = setInt.upper_bound(3);
cout <<"使用lower_bound" << *it1 << endl;
cout <<"使用upper_bound" << *it2 << endl;
pair::iterator, set::iterator> pir = setInt.equal_range(3);
cout << "使用equal_range" << *pir.first << endl;
cout << "使用equal_range" << *pir.second << endl;
return 0;
}
map 是标准的 关联式 容器,一个 map 里存储的元素是一个键值对序列, 叫做(key,value)键值对。它提供基于 key 快速检索数据的能力
map 中 key 值是唯一的 。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。map 底层的具体实现是采用 红黑树变体 的平衡二叉树的数据结构。在插入操作、删除和检索操作上比 vector 快很多。map 可以直接存取 key 所对应的 value ,支持 [] 操作符,如 map[key]=value 。#includemultimap 与 map 的区别 :map 支持唯一键值,每个键只能出现一次;而 multimap 中相同键可以出现多次。 multimap不支持[]操作符,不支持键值操作
map/multimap 对象的默认构造map/multimap 采用模板类实现,对象的默认构造形式:mapmapTT; multimapmultimapTT; 如:mapmapA; mapmapB; //其中 T1,T2 还可以用各种指针类型或自定义类型map 和 multimap 对象的带参数构造方式一:map(beg,end); //将 [beg, end) 区间中的元素拷贝给本身。方式二:map(const map &mapObject); // 拷贝构造函数。
方式一、通过 pair 的方式插入对象
mapStu.insert( pair(1,"张三 ") );方式二、通过 pair 的方式插入对象mapStu.inset(make_pair(2, “李四 ”));方式三、通过 value_type 的方式插入对象mapStu.insert( map::value_type(3,"王五 ") );方式四、通过数组的方式插入值mapStu[4] = "赵六 ";mapStu[5] = “小七 " ;前三种方法,采用的是 insert() 方法,该方法 返回值为 pair,无法进行覆盖操作 cout << "判断是否插入成功:[1/0]: ";
pair第四种方法可以进行覆盖操作,, mapStu[4] = "赵六";mapStu[4] = "王七 ";
map/multimap 排序
map> mapA; // 该容器是按键的升序方式排列元素。未指定函数对象,默认采用 less函数对象。 map> mapB; //该容器是按键的降序方式排列元素。 less与 greater 可以替换成其它的函数对象 functor 。 可编写自定义函数对象以进行自定义类型的比较,使用方法与 set 构造时所用的函数对象一样。
map 对象的拷贝构造与赋值map(const map &mp); //拷贝构造函数map& operator=(const map &mp);//重载等号操作符map.swap(mp); //交换两个集合容器//map2[1].swap(map2[2])//元素交换
map 的大小map.size(); //返回容器中元素的数目map.empty();// 判断容器是否为空和set一样没有resize
map 的删除
map.clear(); //删除所有元素map.erase(pos); //删除 pos 迭代器所指的元素,返回下一个元素的迭代器。map.erase(beg,end);// 删除区间 [beg,end) 的所有元素 ,返回下一个元素的迭代器。map.erase(key); //删除容器中 key 为 key 的对组 , 返回删除的对组个数mapA.erase(4); // 删除容器中 key 为 4 的元素Map.erase(key_type *first, key_type *last) // 删除数组指定的半闭半开的区间中特定的key 对应的所有队组
map/multimap 的查找
map.find(key); 查找键 key 是否存在,若存在,返回该键的元素的迭代器;若不存在,返回 map.end();multimap::iterator it1 = multMap.find(1); if ((*it1).first == 1)
for (; it1 != multMap.end();it1++) {
//方法一循环判断,或者使用count全部遍历
{
cout << (*it1).first << " " << (*it1).second << endl;
}
else break;
}map.count(key); //返回容器中键值为 key 的对组个数。对 map 来说,要么是 0 ,要么是 1; 对 multimap 来说,值 >=0 。map.lower_bound(keyElem); // 返回第一个 key>=keyElem 元素的迭代器。map.upper_bound(keyElem); // 返回第一个 key>keyElem 元素的迭代器。map.equal_range(keyElem); //返回容器中 key 与 keyElem 相等的上下限的两个迭代 器。上限是闭区间,下限是开区间,如[beg,end) 。multimap::iterator it3 = multMap.lower_bound(3);
multimap::iterator it4 = multMap.upper_bound(3);
cout <<"使用lower_bound" << (*it3).second << endl;
cout <<"使用upper_bound" << (*it4).second << endl;
pair::iterator,
multimap::iterator> mit = multMap.equal_range(3);
if (mit.first!=multMap.end())
{
cout << "使用equal_range" << (*mit.first).second << endl;
}
if (mit.second != multMap.end())
{
cout << "使用equal_range" << (*mit.second).second << endl;
}
#include
queue 对象的默认构造
queue 采用模板类实现, queue 对象的默认构造形式: queuequeT; 如:queuequeueInt; //一个存放 int 的 queue 容器。queuequeueFloat; //一个存放 float 的 queue 容器。queuequeueString; //一个存放 string 的 queue 容器。
queue 对象的带参构造queue> queueList; // 内部使用 list 或者deque 来存储队列元素的 queue 容器 .错误 : queue> queueList; // 内部不能使用 vector 来存储队列元素没有front方法
queue 的 push()与 pop()方法
queue.push(elem); //往队尾添加元素queue.pop(); //从队头处移除队首元素
queue 对象的拷贝构造与赋值
queue(const queue &que); //拷贝构造函数queue& operator=(const queue &que); // 重载等号操作符
queue 的数据存取
queue.back(); //返回最后一个元素queue.front(); //返回第一个元素
queue 的大小
queue.empty(); //判断队列是否为空queue.size(); //返回队列的大小不支持resize()
#include
#include
#include
using namespace std;
int main(void) {
queue> que;
que.push(1);
que.push(2);
que.push(3);
que.push(4);
//从前面开始删除
que.pop();
//将第一个值
que.front() = 12;
int front1 = que.front();
//从后面开始放值
que.back() = 12;
int back1 = que.back();
cout << que.size() << endl;
cout <<"第一个元素: " << front1 << endl;
cout <<"最后一个元素: " << back1 << endl;
}
按值的优先级进行打印(默认是值大的优先级越大) ,可以通过vector和deque来设置优先级
//不支持,list,map,set来设置优先级
#include
#include
#include
using namespace std;
int main(void) {
cout << "priority_queue" << endl;
//priority_queue pq;//默认值越大优先级越大
//priority_queue,greater> pq;//值越小优先级越大
priority_queue, greater> pq;//值越小优先级越大
//不支持,list,map,set
pq.push(1);
pq.push(5);
pq.push(4);
pq.push(1);
pq.push(2);
while (!pq.empty()){
cout << pq.top();//按值的优先级打印
pq.pop();
}
}
stack 是堆栈容器,是一种“先进后出”的容器
stack 是基于 deque 容器而实现的容器。#include
stack 的 push()与 pop()方法
stack.push(elem); //往栈头添加元素(入口)stack.pop(); //从栈头移除第一个元素
stack 对象的拷贝构造与赋值
stack(const stack &stk); //拷贝构造函数stack& operator=(const stack &stk); //重载等号操作符
stack 的数据存取
stack.top(); // 返回最后一个压入栈元素
stack 的大小
stack.empty(); //判断堆栈是否为空stack.size(); //返回堆栈的大小
#include
#include
using namespace std;
int main(void) {
stack st;
st.push(1);
st.push(3);
st.push(4);
st.push(2);
st.push(7);
st.push(3);
cout << "st的大小" << st.size() << endl;
while (!st.empty()){
cout << st.top();//按照后进先出
st.pop();//按照后进先出删除
}
}