目录
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>组成
赋值: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;
超出的值直接删除,将大小变为指定值,没有超出则,默认值为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<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(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);? ?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 不可以随机存取元素,所以不支持 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 和 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 是标准的 关联式 容器,一个 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<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;
}
按值的优先级进行打印(默认是值大的优先级越大)?,可以通过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 是基于 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();//按照后进先出删除
}
}