目录
SDL标准模板库分为三类:
放入普通变量
放入普通类
使用指针类对象
详解三类标准库
容器:
vector容器:
访问方式:
vector:resize:改变容器大小和内存(删除值)
vector:pop_back:尾部删除值
vector:erase:指定位置值的删除
vector:iterator
vector:insert:指定位置值的插入
deque 容器
list容器
set&multise容器
map&multimap容器
queue容器(先进先出)
priority_queue
stack容器(后进先出)
SDL标准模板库分为三类:
algorithm(算法):对数据进行处理(解决问题) 步骤的有限集合
container(容器):用来管理一组数据元素
iterator(迭代器):可遍历 STL 容器内全部或部分元素”的对象
#include <algorithm>//算法
#include <vector>//容器
#include <iterator>//迭代器
容器和算法通过迭代器可以进行无缝地连接
。在
STL
中几乎所有的代码都采用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会
[
STL
被组织为下面的
13
个头文 件:
<algorithm>、<deque>、<functional>、<iterator>、<vector>、<list>、<map>、<memory>、<numeric>、<queue>、<set>、<stack> 和<utility>。
]
放入普通变量
//使用标准库三类 void test1() { vector<int> 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<int>::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<Man> 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<<": "<<v1[i].age << " "; } cout << endl; //使用迭代器进行输出 cout << "使用迭代器进行输出" << endl; for (vector<Man>::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<Man*> v1; Man man1("小滕", 22); Man man2("文博波", 24); v1.push_back(&man1); v1.push_back(&man2); //使用迭代器进行输出 cout << "使用迭代器进行输出" << endl; for (vector<Man*>::iterator it = v1.begin(); it != v1.end(); it++) { //迭代器是一个特殊的指针,指向第一个元素,到最后一个元素的下一位 cout << (**it).name << ": " << (**it).age << " ";//对迭代器指针进行解引 } }
详解三类标准库
容器:
容器部分主要有由<vector>,<deque>,<list>,<set>,<map>,<stack> 和<queue>组成
vector容器:
赋值: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] << " "; }
//默认构造函数
vector<int> v1;
//一个存放 int 的 vector 容器
vector<float> v2;
//一个存放 float 的 vector 容器
vector<student> v2; //一个存放 student 的 vector 容器
//vector默认构造.元素个数为0,内存为0 vector<int> v1; //vector<float> 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<int> v2(10, 0);//分配一个长度为10,元素为0的空间 vector<int> v2(10, 6);//分配一个长度为10,所有元素为6的空间 vector<int> 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;
vector:resize:改变容器大小和内存(删除值)
超出的值直接删除,将大小变为指定值,没有超出则,默认值为0
vector:pop_back:尾部删除值
和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;
vector:erase:指定位置值的删除
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] << " "; }
vector:iterator
cout << "使用迭代器输出" << endl; for (vector<int>::iterator it = v1.begin(); it != v1.end();it++){ cout << *it << " "; } cout << endl; cout << "使用使用逆转迭代器输出" << endl; for (vector<int>::reverse_iterator it = v1.rbegin(); it != v1.rend(); it++) { cout << *it << " "; } cout << endl; cout << "使用常量迭代器输出" << endl; for (vector<int>::const_iterator it = v1.cbegin(); it != v1.cend(); it++) { cout << *it << " "; }
vector:insert:指定位置值的插入
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 容器
deque 是双端数组,而 vector 是单端的。
特点:
deque
在接口上和
vector
非常相似,在许多操作的地方可以直接替换。deque
可以随机存取元素(支持索引值直接存取,用
[]
操作符或
at()
方法)deque 头部和尾部添加或移除元素都非常快速
,
但是在中部安插元素或移除元素比较费时。
带参:
方式
1
:deque(beg,end); deque<int> deqIntB(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<int>::iterator it = deqIntA.begin(); it!=deqIntA.end(); ++it){ (*it)++; //*it++ (*it)++ cout<<*it; cout<<" "; } //常量迭代器 deque<int>::const_iterator cit = deqIntA.cbegin(); for( ; cit!=deqIntA.cend(); cit++){ cout<<*cit; cout<<" "; } //逆转的迭代器 for(deque<int>::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
是一个
双向链表容器
,可高效地进行插入删除元素
List 特点:
list 不可以随机存取元素,所以不支持
at.(position)
函数与
[]
操作符。可以对其迭代器执行
++
,但是
不能
这样操作迭代器
:it+3使用时包含 #include <list>
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&multise容器
set 和 multiset 是一个集合容器,其中 set 所包含的元素是唯一的,集合中的元素按一定的顺序排列。set 采用红黑树变体的数据结构实现,红黑树属于平衡二叉树。在插入操作和删除操作上比 vector 快。在 n 个数中查找目标数的效率是 log2n
红黑树的定义:
节点是红色或黑色;
根节点是黑色;
所有叶子节点都是黑色节点(NULL)
;每个
红色节点必须有两个黑色的子节点
。
(
从每个叶子到根的所有路径上不能有两个连续的红色节点。
)从
任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点
Set
和
multiset
特点set
中元素插入过程是
按排序规则插入,所以
不能指定插入位置
。set
不可以直接存取元素。(不可以使用
at.(pos)
与
[]
操作符)。multiset
与
set
的区别:set
支持唯一键值,每个元素值只能出现一次;而
multiset 中
同一值可以出现多次
。不可以直接修改
set
或
multiset
容器中的元素值
,因为该类容器是自动排序的。
如果希望修改一个元素值
,必须先删除原有的元素,再插入新的元素头文件
#include <set>
set<int> setInt; multiset<int> mulInt; //不能指定插入,只能按照顺序插入 cout << "使用set进行顺序赋值," << endl; for (int i = 0; i < 10; i++){ setInt.insert(100 - i); } //不能插入重复的值 setInt.insert(8); for (set<int>::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<int>::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<int,greater<int>> setInt;
set一般会进行默认排序,而这个默认排序就是set库里面通过重载operator()[仿函数]运算符来实现的
当排序的是类对象的时候,既可以通过重载operator><的比较运算符来实现排序,也可以通过set库提供的 重载operator()[仿函数]来实现
#include <iostream> #include <set> 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<Student> stu; stu.insert(Student(13)); stu.insert(Student(14)); stu.insert(Student(12)); stu.insert(Student(16)); cout << "重载比较运算符的结果"<<endl; for (set<Student>::iterator it = stu.begin(); it != stu.end(); it++) { cout << it->getAge() << " "; } cout << endl; cout << "仿函数的结果" << endl; set<Student,FunStudent> stu1; stu1.insert(Student(13)); stu1.insert(Student(14)); stu1.insert(Student(12)); stu1.insert(Student(17)); for (set<Student , FunStudent>::iterator it = stu1.begin(); it != stu1.end(); it++) { cout << it->getAge() << " "; } return 0; }
set 的插入和 pair 的用法
pair 表示一个对组,它将两个值视为一个单元,把两个值捆绑在一起。
pair<T1,T2>
用来存放的两个值的类型,可以不一样,也可以一样,如
T1
为
int
,
T2
为float
。
T1,T2
也可以是自定义类。pair.first 是
pair
里面的第一个值,是
T1
类型。pair.second 是
pair
里面的第二个值,是
T2
类型set<int> setInt;
for(int i=5; i>0; i--){
pair<set<int>::iterator, bool> ret = setInt.insert(i);
if(ret.second){
cout<<"插入 "<<i<<"
成功!
"<<endl;}else {
cout<<"插入 "<<i<<"
失败!
"<<endl;}
}
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<int>
声明的容器,假设它内部现已包含按顺序的
1, 2, 3, 4, 5, 6元素。
set<int>::iterator itBegin=setInt.begin();
++ itBegin;set<int>::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 <iostream> #include <set> using namespace std; int main(void) { set<int> setInt; for (int i = 5; i > 0; i--) { pair<set<int>::iterator , bool> ret = setInt.insert(i); if (ret.second) { cout << "插入" << *ret.first << "成功"; } else { cout << "插入" << i << "失败"; } } setInt.insert(6); cout << endl; cout << "遍历结果是:" << endl; for (set<int>::iterator it = setInt.begin(); it != setInt.end(); it++) { cout << *it << " "; } cout << endl; //删除6 setInt.erase(6); cout << "删除6遍历结果是:" << endl; for (set<int>::iterator it = setInt.begin(); it != setInt.end(); it++) { cout << *it << " "; } cout << endl; cout << "单查找到5的位置是:" << " "; set<int>::iterator it = setInt.find(5); cout << *it << endl; cout << endl; int n = setInt.count(1); cout << n << endl; set<int>::iterator it1 = setInt.lower_bound(3); set<int>::iterator it2 = setInt.upper_bound(3); cout <<"使用lower_bound" << *it1 << endl; cout <<"使用upper_bound" << *it2 << endl; pair<set<int>::iterator, set<int>::iterator> pir = setInt.equal_range(3); cout << "使用equal_range" << *pir.first << endl; cout << "使用equal_range" << *pir.second << endl; return 0; }
map&multimap容器
map
是标准的
关联式
容器,一个
map
里存储的元素是一个键值对序列,
叫做(key,value)键值对。它提供基于
key
快速检索数据的能力
map
中
key
值是唯一的
。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。
map
底层的具体实现是采用
红黑树变体
的平衡二叉树的数据结构。在插入操作、删除和检索操作上比
vector
快很多。map
可以直接存取
key
所对应的
value
,支持
[]
操作符,如
map[key]=value
。#include <map>
multimap
与
map
的区别
:map
支持唯一键值,每个键只能出现一次;而
multimap
中相同键可以出现多次。
multimap不支持[]操作符,不支持键值操作
map/multimap
对象的默认构造map/multimap 采用模板类实现,对象的默认构造形式:
map<T1,T2> mapTT;
multimap<T1,T2> multimapTT;
如:
map<int, char> mapA;
map<string,float> mapB; //其中
T1,T2
还可以用各种指针类型或自定义类型map
和
multimap
对象的带参数构造方式一:map(beg,end); //将
[beg, end)
区间中的元素拷贝给本身。方式二:map(const map &mapObject); //
拷贝构造函数。
方式一、通过 pair 的方式插入对象
mapStu.insert( pair<int,string>(1,"张三
") );方式二、通过
pair
的方式插入对象mapStu.inset(make_pair(2, “李四
”));方式三、通过
value_type
的方式插入对象mapStu.insert( map<int,string>::value_type(3,"王五
") );方式四、通过数组的方式插入值
mapStu[4] = "赵六
";mapStu[5] = “小七
"
;前三种方法,采用的是
insert()
方法,该方法
返回值为 pair<iterator,bool>,无法进行覆盖操作 cout << "判断是否插入成功:[1/0]: ";
pair<map<int, string>::iterator ,bool>
it = map1.insert(map<int, string>::value_type(2, "贰拾"));
cout << it.second << endl;第四种方法可以进行覆盖操作,,
mapStu[4] = "赵六";mapStu[4] = "王七
";
map/multimap 排序
map<T1,T2,less<T1> > mapA; //
该容器是按键的升序方式排列元素。未指定函数对象,默认采用
less<T1>
函数对象。map<T1,T2,greater<T1>> mapB; //该容器是按键的降序方式排列元素。
less<T1>
与
greater<T1>
可以替换成其它的函数对象
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<int, string>::iterator it1 = multMap.find(1);
for (; it1 != multMap.end();it1++) {
//方法一循环判断,或者使用count全部遍历
if ((*it1).first == 1)
{
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<int, string>::iterator it3 = multMap.lower_bound(3);
multimap<int, string>::iterator it4 = multMap.upper_bound(3);
cout <<"使用lower_bound" << (*it3).second << endl;
cout <<"使用upper_bound" << (*it4).second << endl;
pair<multimap<int, string>::iterator,
multimap<int, string>::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 <map> #include <iostream> using namespace std; int main(void) { map<int, string> map1; map1.insert(pair<int, string> (1, "张飒")); map1.insert(map<int, string>::value_type(2, "贰拾")); map1.insert(make_pair(3, "王五")); map1.insert(pair<int, string>(4, "六码")); //multimap不支持这种方式 //使用insert不能在同一个键进行覆盖 // map1.insert(pair<int, string> (1, "张飒")); // map1.insert(pair<int, string> (1, "覆盖张飒"));//失败 //[]可以 map1[5] = "键值"; map1[5] = "覆盖键值"; for (map<int ,string>::iterator it = map1.begin(); it !=map1.end(); it++) { cout << "序号:" << (*it).first << "姓名;" << (*it).second << endl; } //判断是否插入成功 cout << "判断是否插入成功:[1/0]: "; pair<map<int, string>::iterator ,bool> it = map1.insert(map<int, string>::value_type(2, "贰拾")); cout << it.second << endl; //执行拷贝之后 cout << "执行拷贝之后" << endl; map<int, string> map2(map1); for (map<int, string>::iterator it = map2.begin(); it != map2.end(); it++) { cout << "序号:" << (*it).first << "姓名;" << (*it).second << endl; } cout << "交换1, 2之后" << endl; map2[1].swap(map2[2]); for (map<int, string>::iterator it = map2.begin(); it != map2.end(); it++) { cout << "序号:" << (*it).first << "姓名;" << (*it).second << endl; } cout << "删除1对应的值之后" << endl; map2.erase(1); for (map<int, string>::iterator it = map2.begin(); it != map2.end(); it++) { cout << "序号:" << (*it).first << "姓名;" << (*it).second << endl; } cout << endl; cout << "使用multmap进行查找重复的值" << endl; multimap<int, string> multMap; multMap.insert(pair<int, string>(1, "张飒")); multMap.insert(pair<int, string>(1, "张三")); multMap.insert(map<int, string>::value_type(2, "贰拾")); multMap.insert(make_pair(3, "王五")); multMap.insert(pair<int, string>(4, "六码")); multimap<int, string>::iterator it1 = multMap.find(1); for (; it1 != multMap.end();it1++) { //方法一循环判断,或者使用count全部遍历 if ((*it1).first == 1) { cout << (*it1).first << " " << (*it1).second << endl; } else break; } multimap<int, string>::iterator it3 = multMap.lower_bound(3); multimap<int, string>::iterator it4 = multMap.upper_bound(3); cout <<"使用lower_bound" << (*it3).second << endl; cout <<"使用upper_bound" << (*it4).second << endl; pair<multimap<int, string>::iterator, multimap<int, string>::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; } }
queue容器(先进先出)
queue 对象的默认构造
queue 采用模板类实现,
queue
对象的默认构造形式:
queue<T> queT;
如:queue<int> queueInt; //一个存放
int
的
queue
容器。queue<float> queueFloat; //一个存放
float
的
queue
容器。queue<string> queueString; //一个存放
string
的
queue
容器。
queue
对象的带参构造queue<int, list<int>> queueList; //
内部使用
list 或者deque
来存储队列元素的
queue
容器
.错误
: queue<int, vector<int>> 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 <iostream> #include <queue> #include <list> using namespace std; int main(void) { queue<int, list<int>> 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; }
priority_queue
按值的优先级进行打印(默认是值大的优先级越大) ,可以通过vector和deque来设置优先级
//不支持,list,map,set来设置优先级
#include <iostream> #include <queue> #include <list> using namespace std; int main(void) { cout << "priority_queue" << endl; //priority_queue<int> pq;//默认值越大优先级越大 //priority_queue<int,vector<int>,greater<int>> pq;//值越小优先级越大 priority_queue<int, deque<int>, greater<int>> 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 是堆栈容器,是一种“先进后出”的容器
stack
是基于
deque
容器而实现的容器。#include <stack>
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<iostream> #include <stack> using namespace std; int main(void) { stack<int> 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();//按照后进先出删除 } }