目录
1.STL初识
1.1 STL的诞生
-
长久以来,软件界一只希望建立一种可重复利用的体系
-
C++的面向对象和泛型编程思想,目的在于提升复用性
-
多数情况下,数据结构和算法都未能有一套标准,导致被迫进行大量重复性工作
-
为建立数据结构和算法的一套标准,STL应运而生
1.2 STL基本概念
-
STL(Standard Template Library) —— 标准模板库
-
从广义上分为
-
容器(container)
-
算法(algorithm)
-
迭代器(iterator)
-
-
容器和算法之间通过迭代器进行无缝连接
-
STL 几乎所有的代码都采用了模板类或模板函数
1.3 STL六大组件
-
大体分为六大组件:
-
容器
-
算法
-
迭代器
-
仿函数
-
适配器(配接器)
-
空间配置器
-
1.容器 —— 各种数据结构,如 vector、list、deque、set、map等,用来存放数据。
2.算法 —— 各种常用的算法,如sort、find、copy、for_each等。
3.迭代器 —— 扮演了容器与算法之间的胶合剂。
4.仿函数 —— 行为类似函数,可作为算法的某种策略。
5.适配器 —— 一种用来修饰容器或者仿函数或迭代器接口的东西。
6.空间配置器 —— 负责空间的配置与管理
1.4 STL 之 容器、算法、迭代器
容器 —— 置物之所也。
STL容器就是将运用最广泛的一些数据结构实现出来。
常用的数据结构 —— 数组,链表,树,栈队列,集合,映射表等。
这些容器分为序列式容器和关联式容器两种: 1.序列式容器 —— 强调值的排序,序列式容器中的每个元素均有固定的位置。
2.关联式容器 —— 二叉树结构。各元素之间没有严格的物理上的顺序关系。
算法 —— 问题之解法也
有限的步骤,解决逻辑或数学上的问题,这一门学科我们叫做算法(Algorithms)。
算法分为 —— 质变算法和非质变算法。 1.质变算法 —— 是指运算过程中会更改区间内的元素的内容,例如拷贝、替换,删除等。
2.非质变算法 —— 是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等。
迭代器 —— 容器与算法之间的粘合剂
提供一种方法,使之能够按序寻访某个容器所含的各个元素,且无需暴露该容器的内部表示方式。
每个容器都有自己的专属迭代器。
迭代器使用非常类似于指针。
迭代器种类:
种类 | 功能 | 支持运算 |
---|---|---|
输入迭代器 | 对数据的只读访问 | 只读,支持++、==、!= |
输出迭代器 | 对数据的只写访问 | 只写,支持++ |
前向迭代器 | 读写操作,并能向前推进迭代器 | 读写。支持++、==、!= |
双向迭代器 | 读写操作,并能向前和向后操作 | 读写,支持++ |
随机访问迭代器 | 读写操作,可以跳跃式访问任意数据,功能最强的迭代器 | 读写,支持++、--、[n]、-n、<、<=、>、>= |
常用的容器中迭代器种类为双向迭代器,和随机访问迭代器。
1.5 容器、算法、迭代器 初识
1.5.1 vector 存放内置数据类型
容器:vector
算法:for_each
迭代器:vector::iterator
示例:
#include <vector> #include <algorithm> void MyPrint(int val) { cout << val << " "; } int main () { // 创建vector容器 vector<int> v; // 数据添加 v.push_pack(10); v.push_pack(20); v.push_pack(30); // 创建vector迭代器 vector<int>::iterator itBegin = v.begin(); // 起始迭代器 vector<int>::iterator itEnd = v.end(); // 结束迭代器 指向最后元素的下一位置 // 遍历方法1 while (itBegin != itEnd) { cout << *itBegin << " "; } // 遍历方法2 for (vector<int> it = v.begin(); it != v.end(); it++) { cout << *it << " "; } // 遍历方法3 for_each(v.begin, v.end(), MyPrint); return 0; }
1.5.2 Vector 存放自定义数据类型
示例:
#include <iosteam> #include <string> #include <vector> class Person { public: Person(string name, int age) { this -> m_Name = name; this -> m_Age = age; } string m_Name; int m_Age; }; void test01() { // 创建vector容器 vector<Person> v; // 添加数据 v.push_back(Person("aa", 10)); v.push_back(Person("bb", 20)); v.push_back(Person("cc", 30)); v.push_back(Person("dd", 40)); v.push_back(Person("ee", 50)); // 遍历 + 指针成员 for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) { cout << "Name: " << it->m_Name << " Age: " << it->m_Age << endl; } } void test02 () { // 创建vector容器 vector<Person> v; // 添加数据 v.push_back(Person("aa", 10)); v.push_back(Person("bb", 20)); v.push_back(Person("cc", 30)); v.push_back(Person("dd", 40)); v.push_back(Person("ee", 50)); // 遍历 + 解引用 for (vector<Person>::iterator it = v.begin(); it != v.end(); it++) { cout << "Name: " << (*it).m_Name << " Age: " << (*it).m_Age << endl; } } // 存储自定义类型指针 void test03 () { // 创建vector容器 vector<Person*> v; // 创建测试数据 Person p1("aa", 10); Person p2("bb", 20); Person p3("cc", 30); Person p4("dd", 40); Person p5("ee", 50); // 添加数据 v.push_back(&p1); v.push_back(&p2); v.push_back(&p3); v.push_back(&p4); v.push_back(&p5); // 遍历 for (vector<Person*>::iterator it = v.begin(); it != v.end(); it++) { cout << "Name: " << (*it)->m_Name << " Age: " << (*it)->m_Age << endl; } } int main () { test01(); test02(); test03(); }
2 STL 常用容器
2.1 string 容器
2.1.1 string 基本概念
本质:
-
string 是 C++ 风格的字符串,但string 本质上是一个类
string 和 char* 的区别:
-
char* 是一个指针
-
string 是一个类,类内部封装了char* ,管理这个字符串,是一个char* 类型的容器
特点:
-
string 类内部封装了很多成员方法
-
例如:查找find,拷贝copy,删除delete,替换replace,插入insert
-
string 管理插入char* 所分配的内存,不用担心复制越界或取值越界等,由类的内部进行负责。
2.1.2 string 构造函数
构造函数原型:
-
string();
—— 创建一个空的字符串 例如:string strstring(const char* s);
—— 使用字符串s初始化 -
string(const string& str);
—— 使用一个string对象初始化另一个string对象 -
string(int n, char c);
—— 使用n个字符c初始化
示例:
#include <iostream> using namespace std; // string构造函数 void test01() { string s1; // 默认构造 const char * str = "hello~"; string s2(str); cout << "s2 = " << s2 << endl; string s3(s2); cout << "s3 = " << s3 << endl; string s4(10, 'a'); cout << "s4 = " << s4 << endl; } int main() { test01(); return 0; }
总结:string 的用法无需对比,灵活使用即可。
2.1.3 string 的赋值操作
功能描述:
-
给string字符串进行赋值
赋值的函数类型:
-
string& operator = (const char* s);
-
char* 类型字符串 赋值给当前的字符串
-
-
string& operator = (const string &s);
-
把字符串s 赋给当前的字符串
-
-
string& operator = (char c);
-
字符赋值给当前的字符串
-
-
string& assign(const char *s);
-
把字符串s 赋给当前的字符串
-
-
string& assign(const char *s, int n);
-
把字符串s 的前n 个字符赋给当前的字符串
-
-
string& assign(const string &s);
-
把字符串s 赋给当前字符串
-
-
string& assign(int n, char c);
-
用n 个字符c 赋给当前字符串
-
示例:
#include <iostream> using namespace std; #include <string> // void test01() { string str1; str1 = "hello!!"; cout << "str1 = " << str1 << endl; string str2; str2 = str1; cout << "str2 = " << str2 << endl; string str3; str3 = 'x'; cout << "str3 = " << str3 << endl; string str4; str4.assign("hello C++!!"); cout << "str4 = " << str4 << endl; // ?? string str5; str5.assign("hello c++!", 5); cout << "str5 = " << str5 << endl; string str6; str6.assign(str5); cout << "str6 = " << str6 << endl; string str7; str7.assign(10, 'x'); cout << "str7 = " << str7 << endl; } int main() { test01(); return 0; }
2.1.4 string 字符串拼接
功能描述:
-
实现在字符串末尾拼接字符串
函数原型:
-
string& operator += (const char* str);
-
重载 += 操作符
-
-
string& operator += (const char c);
-
重载 += 操作符
-
-
string& operator += (const string &str);
-
重载 += 操作符
-
-
string& append(const char *s);
-
把字符串s 连接到当前字符串结尾
-
-
string& append(const char *s, int n);
-
把字符串s 的前n 个字符连接到当前字符串结尾
-
-
string& append(const string &s);
-
同operator += (const string &str)
-
-
string& append(const string &s, int pos, int n);
-
字符串s 中从pos 开始的n 个字符连接到字符串结尾
-
示例:
#include <iostream> using namespace std; void test01() { string str1 = "I"; str1 += " love study"; cout << "str1 = " << str1 << endl; str1 += "!"; cout << "str1 = " << str1 << endl; string str2 = "Hey, "; str2 += str1; cout << "str2 = " << str2 << endl; string str3 = "You"; str3.append(" love "); cout << "str3 = " << str3 << endl; str3.append("nothing abc", 8); cout << "str3 = " << str3 << endl; str3.append(str1); cout << "str3 = " << str3 << endl; str3.append(str2, 0, 3); cout << "str3 = " << str3 << endl; } int main() { test01(); return 0; }
2.1.5 string 查找和替换
功能描述:
-
查找:查找指定字符串是否存在
-
替换:在指定的位置替换字符串
函数原型:
-
int find(const string &str, int pos = 0) const;
-
查找str 第一次出现位置,从pos开始查找
-
-
int find(const char* s , int pos = 0) const;
-
查找s 第一次出现位置,从pos开始查找
-
-
int find(const char* s , int pos, int n) const;
-
从pos 位置查找s 的前n 个字符第一次位置
-
-
int find(const char c, int pos = 0) const;
-
查找字符c 第一次出现位置
-
-
int rfind(const string& str, int pos = npos ) const;
-
查找str 最后一次位置,从pos 开始查找
-
-
int rfind(const char* s, int pos = npos) const;
-
查找s 最后一次出现位置,从pos开始查找
-
-
int rfind(const char* s, int pos, int n) const;
-
从pos 查找s 的前n 个字符最后一次位置
-
-
int rfind(const char c, int pos = 0) const;
-
查找字符c 最后一次出现位置
-
-
string& replace(int pos, int n, const string& str);
-
替换从pos 开始n 个字符为字符串str
-
-
string& replace(int pos, int n, const char* s );
-
替换从pos 开始的n 个字符为字符串s
-
示例:
#include <iostream> using namespace std; // 查找 void test01() { string str1 = "abcdefgde"; int pos = str1.find("de"); if (pos == -1) { cout << "Not found" << endl; } else { cout << "Found, pos = " << pos << endl; } //rfind 从右往左查找 pos = str1.rfind("de"); cout << "pos = " << pos << endl; } // 替换 void test02() { string str2 = "abcdefg"; str2.replace(1, 3, "1111"); cout << "str2 = " << str2 << endl; } int main() { test01(); test02(); return 0; }
2.1.6 string 字符串比较
功能描述:
-
字符串之间的比较
比较方式:
-
字符串比较是按字符的ASCII进行对比
= 返回 0
> 返回 1
< 返回 -1
函数原型:
-
int compare(const string &s) const;
-
与字符串s 进行比较
-
-
int compare(const char *s) const;
-
与字符串s 进行比较
-
示例:
#include <iostream> using namespace std; // 字符串比较操作 void test01 () { string str1 = "hello"; string str2 = "hello"; if (str1.compare(str2) == 0) { cout << "str1 = str2" << endl; } else if (str1.compare(str2) == 1) { cout << "str1 > str2" << endl; } else { cout << "str1 < str2" << endl; } } int main() { test01(); return 0; }
2.1.7 string 字符存取
string 中单个字符存取方式有两种
-
char& operator[](int n);
-
通过[] 方式取字符
-
-
char& at(int n);
-
通过at 方法获取字符
-
示例:
#include <iostream> using namespace std; // void test() { string str = "hello"; cout << "str = " << str << endl; // 1.通过 [] 来访问单个字符 for (int i = 0; i < str.size(); i++) { cout << str[i] << " "; } cout << endl; // 2.通过 at 方式访问单个字符 for (int i = 0; i < str.size(); i++) { cout << str.at(i) << " "; } cout << endl; // 修改单个字符 str[0] = 'x'; cout << "str = " << str << endl; str.at(1) = 'x'; cout << "str = " << str << endl; } int main() { test(); return 0; }
2.1.8 string 插入 和 删除
功能描述:
-
对string 字符串进行插入和删除字符操作
函数原型:
-
string& insert(int pos, const char* s);
-
插入字符串
-
-
string& insert(int pos, const string& str);
-
插入字符串
-
-
string& insert(int pos, int n, char c);
-
在指定位置插入n 个字符c
-
-
string& erase(int pos, int n = npos);
-
删除从pos 开始的n 个字符
-
示例:
#include <iostream> using namespace std; #include <vector> // 字符串插入 和 删除 void test() { string str = "hello"; cout << "str = " << str << endl; str.insert(1, "111"); cout << "str = " << str << endl; // 删除 str.erase(1, 3); cout << "str = " << str << endl; } int main(){ test(); return 0; }
总结:
-
插入和删除的起始下标均为0
2.1.9 string子串
功能描述:
-
从字符串中获取想要的字符串
函数原型:
-
string sbstr(int pos = 0, int n = npos) const;
-
返回由pos 开始的n 个字符组成的字符串
-
示例:
#include <iostream> using namespace std; // string 求子串 void test01() { string str = "abcdef"; string subStr = str.substr(0, 2); // ab cout << "subStr = " << subStr << endl; } void test02() { string email = "hello@sina.com"; // 从邮件地址中获取用户名信息 int pos = email.find('@'); string userName = email.substr(0, pos); cout << "userName = " << userName << endl; } int main(){ test01(); test02(); return 0; }
2.2 vector 容器
2.2.1 vector 的基本概念
功能:
-
vector 数据结构和数字非常相似,也称为单端数组
vector 与普通数组的区别:
-
数组是静态空间,而vector 可以动态扩展
动态扩展:
-
并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝到新空间,释放原空间
-
vector 容器的迭代器是支持随机访问的迭代器
2.2.2 vector 构造函数
功能描述:
-
创建vector 容器
函数原型:
-
vector<T> v
-
采用模板实现类,默认构造函数
-
-
vector(v.begin(), v.end());
-
将v.begin() 到 v.end() 拷贝给本身
-
-
vector(n, elem);
-
构造函数将n 个elem 拷贝给本身
-
-
vector(const vector &vec);
-
拷贝构造函数
-
示例:
#include <iostream> #include <vector> using namespace std; void printVector(vector<int>&v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { vector<int> v1; // 默认构造,无参构造 for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1); // 通过区间方式进行构造 vector<int>v2(v1.begin(), v1.end()); printVector(v2); // n个elem 方式构造 vector<int> v3(10, 100); printVector(v3); // 拷贝构造 --- vector<int> v4(v3); printVector(v4); } int main() { test01(); }
2.2.3 vector 赋值操作
功能描述:
-
给vector 容器进行赋值
函数原型:
-
vector& operator = (const vector &vec);
-
重载等号操作符
-
-
assign(beg, end);
-
将[beg, end) 区间中的数据拷贝赋值给本身
-
-
assign(n, elem);
-
将n 个elem 拷贝赋值给本身
-
示例:
#include <iostream> #include <vector> using namespace std; void printVector(vector<int>&v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } // vector 赋值 void test01() { vector<int>v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1); vector<int>v2; v2 = v1; printVector(v2); // assign vector<int>v3; v3.assign(v1.begin(), v1.end()); printVector(v3); vector<int>v4; v4.assign(10, 3); printVector(v4); } int main() { test01(); return 0; }
2.2.4 vector 容量和大小
功能描述:
-
对vector 容器的容量和大小操作
函数原型:
-
empty();
-
判断容器是否为空
-
-
capacity();
-
容器的容量
-
-
size();
-
返回容器中元素的个数
-
-
resize(int num);
-
重新指定容器的长度为 num,若容器变长,则以默认值填充新位置
-
如果容器变短,则末尾超出容器长度的元素被删除
-
-
resize(int num, elem);
-
重新指定容器长度为 num,若容器变长,则以elem 值填充新位置
-
如果容器变短,则末尾超出容器长度的元素被删除
-
示例:
#include <iostream> #include <vector> using namespace std; void printVector(vector<int>&v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } // vector 容器量 和 大小的操作 void test01() { vector<int>v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1); // if (v1.empty()) { cout << "empty" << endl; } else { cout << "not empty" << endl; cout << "capacity = " << v1.capacity() << endl; cout << "szie = " << v1.size() << endl; // 重新指定大小 v1.resize(15, 1); // 过长未赋值部分默认以0 填充 printVector(v1); v1.resize(5); // 指定size 过短,超出部分被删除 printVector(v1); } } int main() { test01(); system("pause"); return 0; }
2.2.5 vector 插入 和 删除
功能描述:
-
对vector 容器进行插入、删除操作
函数原型:
-
push_back(ele);
-
尾部插入元素ele
-
-
pop_back();
-
删除最后一个元素
-
-
insert(const_iterator pos, ele);
-
迭代器指向位置pos 插入元素ele
-
-
insert(const_iterator pos, int count, ele);
-
迭代器指向位置pos 插入count 个元素ele
-
-
erase(const_iterator pos);
-
删除迭代器指向的元素
-
-
erase(const_iterator start, const_iterator end);
-
删除迭代器从start 到end 之间的元素
-
-
clear();
-
删除容器中所有的元素
-
示例:
#include <iostream> #include <vector> using namespace std; void printVector(vector<int>&v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } // vector 插入和 删除 void test01() { vector<int>v1; // 尾插法 v1.push_back(10); v1.push_back(20); v1.push_back(30); v1.push_back(40); v1.push_back(50); // 遍历 printVector(v1); // 尾删法 v1.pop_back(); printVector(v1); // 插入 v1.insert(v1.begin(), 100); printVector(v1); v1.insert(v1.begin(), 2, 1000); printVector(v1); // 删除 v1.erase(v1.begin()); printVector(v1); // 类似于 清空 v1.erase(v1.begin(), v1.end()); printVector(v1); // clear v1.clear(); printVector(v1); } int main() { test01(); system("pause"); return 0; }
总结:
-
尾插 —— push_back
-
尾删 —— pop_back
-
插入 —— insert(位置迭代器)
-
删除 —— erase(位置迭代器)
-
清空 —— clear
2.2.6 vector 数据存取
功能描述:
-
对 vector 中的数据的存取操作
函数原型:
-
at(int idx);
-
返回索引idx 所指的数据
-
-
operator[];
-
返回索引idx 所指的数据
-
-
front();
-
返回容器中第一个数据元素
-
-
back();
-
返回容器中最后一个元素
-
示例:
#include <iostream> #include <vector> #include "print.h" using namespace std; //void printVector(vector<int>&v) { // for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { // cout << *it << " "; // } // cout << endl; //} // vector 数据存取 void test01() { vector<int>v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } // 下标访问元素 for (int i = 0; i < v1.size(); i++) { cout << v1[i] << " "; } cout << endl; // at方法访问 for (int i = 0; i < v1.size(); i++) { cout << v1.at(i) << " "; } cout << endl; // 返回第一个元素 cout << v1.front() << endl; // 返回最后一个元素 cout << v1.back() << endl; } int main() { test01(); system("pause"); return 0; }
2.2.7 vector 互换容器
功能描述:
-
实现两个容器内元素进行互换
函数原型:
-
swap(vec);
-
将vec 与本身的元素互换
-
示例:
#include <iostream> #include <vector> #include "print.h" using namespace std; //void printVector(vector<int>&v) { // for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { // cout << *it << " "; // } // cout << endl; //} // vector 容器互换 // 1.基本使用 void test01() { vector<int>v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } cout << "v1 before:" << endl; printVector(v1); vector<int>v2; for (int i = 10; i > 0; i--) { v2.push_back(i); } cout << "v2 before:" << endl; printVector(v2); cout << "after:" << endl; v1.swap(v2); // swap printVector(v1); printVector(v2); } // 2.实际应用 —— 收缩内存空间 void test02() { vector<int>v; for (int i = 0; i < 100000; i++) { v.push_back(i); } cout << "capacity = " << v.capacity() << endl; cout << "size = " << v.size() << endl; // 空间浪费 v.resize(3); cout << "capacity = " << v.capacity() << endl; cout << "size = " << v.size() << endl; // 巧用swap 收缩内存 vector<int>(v).swap(v); // 匿名对象 cout << "capacity = " << v.capacity() << endl; cout << "size = " << v.size() << endl; } int main() { // test01(); test02(); system("pause"); return 0; }
2.2.8 vector 预留空间
功能描述:
-
减少vector 在动态扩展容量时的扩展次数
函数原型:
-
reserve(int len);
-
容器预留len 个元素的长度,预留位置不初始化,元素不可访问
-
示例:
#include <iostream> #include <vector> #include "print.h" using namespace std; //void printVector(vector<int>&v) { // for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { // cout << *it << " "; // } // cout << endl; //} // vector 预留空间 void test01() { vector<int>v; // 利用reserve预留空间 v.reserve(10000); int num = 0; // 统计内存分配次数 int *p = NULL; for (int i = 0; i < 100000; i++) { v.push_back(i); if (p != &v[0]) { p = &v[0]; num++; } } // num = 30 => num = 1 cout << "num = " << num << endl; } int main() { test01(); system("pause"); return 0; }
2.3 deque 容器
2.3.1 deque 容器基本概念
功能:
-
双端数组,可以对头端进行插入删除操作
deque 与vector 区别:
-
vector 对于头部的插入删除效率低,数据量越大,效率越低
-
deque相对而言,对头部的插入删除速度会比vector 快
-
vector 访问元素的速度会比deque 快,这和两者内部实现有关
deque 内部工作原理:
-
deque 内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据
-
中控器维护每个缓冲区的地址,使得使用deque时像一片连续的内存空间
-
deque 容器的迭代器也是支持随机访问的
2.3.2 deque 构造函数
功能描述:
-
deque 容器构造
函数原型:
-
deque<T> deqT;
-
默认构造方式
-
-
deque(beg, end);
-
构造函数将[beg, end)区间中的元素拷贝给本身
-
-
deque(n, elem);
-
构造函数将n 个elem 拷贝给本身
-
-
deque(const deque &deq);
-
拷贝构造函数
-
示例:
#include <iostream> #include <deque> #include "print.h" using namespace std; // deque 构造函数 void test() { deque<int>d1; for (int i = 0; i < 10; i++) { d1.push_back(i); } printDeque(d1); deque<int>d2(d1.begin(), d1.end()); printDeque(d2); deque<int>d3(10, 100); printDeque(d3); deque<int>d4(d3); printDeque(d4); } int main() { test(); return 0; } // printDeque()只读状态 void printDeque(const std::deque<int>&d) { for (std::deque<int>::const_iterator it = d.begin(); it != d.end(); it++) { std::cout << *it << " "; } std::cout << std::endl; }
2.3.3 deque 赋值操作
功能描述:
-
给deque 容器进行赋值
函数原型:
-
deque& operator = (const deque &deq);
-
重载等号操作符
-
-
assign(beg, end);
-
将[beg, end) 区间中的数据拷贝赋值给本身
-
-
assign(n, elem);
-
将n 个elem 拷贝赋值给本身
-
示例:
#include <iostream> #include <deque> #include "print.h" using namespace std; // deque 赋值操作 void test() { deque<int>d1; for (int i = 0; i < 10; i++) { d1.push_back(i); } printDeque(d1); // = 赋值 deque<int>d2; d2 = d1; printDeque(d2); // assign 1 deque<int>d3; d3.assign(d1.begin(), d1.end()); printDeque(d3); // assign 2 deque<int>d4; d4.assign(10, 100); printDeque(d4); } int main() { test(); return 0; }
2.3.4 deque 大小操作
功能描述:
-
对deque 容器的大小进行操作
函数原型:
-
deque.empty();
-
deque.size();
-
deque.resize(int num);
-
deque.resize(int num, elem);
类似于vector,区别在于无容量的概念
示例:
#include <iostream> #include <deque> #include "print.h" using namespace std; // deque 大小操作 void test() { deque<int>d1; for (int i = 0; i < 10; i++) { d1.push_back(i); } printDeque(d1); // empty or not if (d1.empty()) { cout << "empty" << endl; } else { cout << "not empty" << endl; cout << "size = " << d1.size() << endl; // 没有容量概念 } // 重新指定大小 d1.resize(15); printDeque(d1); d1.resize(16, 1); printDeque(d1); d1.resize(5); printDeque(d1); } int main() { test(); return 0; }
总结:
-
deque 没有容量的概念
-
判断是否为空 —— empty
-
返回元素个数 —— size
-
重新指定个数 —— resize
2.3.5 deque 插入和删除
概念描述:
-
向deque 容器中插入和删除数据
函数原型:
两端插入操作:
-
push_back(elem);
-
push_front(elem);
-
pop_back();
-
pop_front();
指定位置操作:
-
insert(pos, elem);
-
返回新数据的位置
-
-
insert(pos, n, elem);
-
无返回值
-
-
insert(pos, beg, end);
-
无返回值
-
-
clear();
-
清空所有元素
-
-
erase(beg, end);
-
返回下一个数据的位置
-
-
erase(pos);
-
返回下一个数据的位置
-
示例:
#include <iostream> #include <deque> #include "print.h" using namespace std; // deque 插入和删除 // 两端操作 void test01() { deque<int>d1; // 尾插法 d1.push_back(10); d1.push_back(20); // 头插法 d1.push_front(100); d1.push_front(200); // 200 100 10 20 printDeque(d1); // 尾删 d1.pop_back(); printDeque(d1); // 头删 d1.pop_front(); printDeque(d1); } void test02() { deque<int>d1; d1.push_back(10); d1.push_back(20); d1.push_front(100); d1.push_front(200); printDeque(d1); // insert // 1000 200 100 10 20 d1.insert(d1.begin(), 1000); printDeque(d1); // 10000 10000 1000 200 100 10 20 d1.insert(d1.begin(), 2, 10000); printDeque(d1); // 按照区间进行插入 deque<int>d2; d2.push_back(1); d2.push_back(2); d2.push_back(3); d1.insert(d1.begin(), d2.begin(), d2.end()); // 1 2 3 10000 10000 1000 200 100 10 20 printDeque(d1); } // 删除 void test03() { deque<int>d1; d1.push_back(10); d1.push_back(20); d1.push_front(100); d1.push_front(200); deque<int>::iterator it = d1.begin(); it++; d1.erase(it); // 200 10 20 printDeque(d1); // 区间删除 d1.erase(d1.begin(), d1.end()); printDeque(d1); // clear d1.clear(); printDeque(d1); } int main() { test01(); test02(); test03(); return 0; }
总结:
-
插入和删除提供的都是迭代器!
-
尾删 —— pop_back
-
尾插 —— push_back``
-
头插 —— push_front
-
头删 —— pop_front
2.3.6 deque 数据存取
功能描述:
-
对deque 中的数据进行存取操作
函数原型:
-
at(int idx);
-
operator[];
-
front();
-
back();
示例:
#include <iostream> #include <deque> #include "print.h" using namespace std; // deque 数据存取 void test01() { deque<int> d1; for (int i = 0; i < 10; i++) { d1.push_back(i); } printDeque(d1); // at方式 for (int i = 0; i < d1.size(); i++) { cout << d1.at(i) << " "; } cout << endl; // []方式 for (int i = 0; i < d1.size(); i++) { cout << d1[i] << " "; } cout << endl; // front cout << d1.front() << endl; // back cout << d1.back() << endl; } int main() { test01(); return 0; }
总结:
-
除了用迭代器获取deque 中的元素以外,[] 和 at 也可
-
front 返回首个
-
back 返回末尾
2.3.7 deque 排序
功能描述:
-
利用算法实现对deque 容器进行排序
算法:
-
sort(iterator beg, iterartor end);
示例:
#include <iostream> #include <deque> // 标准算法头文件 #include <algorithm> #include "print.h" using namespace std; // deque 数据存取 void test01() { deque<int>d; d.push_back(10); d.push_back(20); d.push_back(30); d.push_front(100); d.push_front(200); d.push_front(300); printDeque(d); // sort 默认升序 // 对于支持随机访问的迭代器,都可以使用sort算法排序 sort(d.begin(), d.end()); cout << "ordered: " << endl; printDeque(d); } int main() { test01(); return 0; }
2.4 stack 容器
2.4.1 stack 概念
概念:
-
stack —— 一种先进后出(LIFO)的数据结构,只有一个出口
-
栈中只有顶端元素才可以被外部使用,不允许有遍历操作
2.4.2 stack 常用接口
功能描述:
-
栈容器常用的对外接口
构造函数:
-
stack<T> stk;
-
默认构造方式
-
-
stack(const stack &stk);
-
拷贝构造函数
-
赋值操作:
-
stack& operator = (const &stk);
-
重载等号操作符
-
数据存取:
-
push(elem);
-
向栈顶添加元素
-
-
pop();
-
从栈顶弹出元素
-
-
top();
-
返回栈顶元素
-
大小操作:
-
empty();
-
判断栈是否为空
-
-
size();
-
返回栈的大小
-
示例:
#include <iostream> #include <stack> using namespace std; // stack void test01() { // definition stack<int>s; // 入栈 s.push(10); s.push(20); s.push(30); s.push(40); cout << "size = " << s.size() << endl; // 只要栈不为空,就查看栈顶并执行出栈操作 while (!s.empty()) { // 查看栈顶元素 cout << "top = " << s.top() << endl; // 出栈 s.pop(); } cout << "size of s is: " << s.size() << endl; } int main () { test01(); return 0; }
总结:
-
入栈 —— push
-
出栈 —— pop
-
返回栈顶 —— top
-
判断是否为空 —— empty
-
返回栈大小 —— size
2.5 queue 容器
2.5.1 queue 基本概念
概念:
-
Queue 是一会走先进先出(FIFO)的数据结构,它有两个出口
-
队列容器允许从一端新增元素,从另一端移除元素
-
队列中只有队头和队尾可以被外界使用,因此队列不允许有遍历行为
-
队列中进数据称为 —— 入队
push
-
队中中出数据称为 —— 出队
pop
2.5.2 queue 常用接口
功能描述:
-
栈容器常用的对外接口
构造函数:
-
queue<T> que;
-
queue(const queue &que);
赋值操作:
-
queue& operator = (const queue &que);
数据存取:
-
push(elem);
-
pop();
-
back();
-
front();
大小操作:
-
empty();
-
size();
示例:
#include <iostream> #include <queue> using namespace std; // queue class Person { public: Person(string Name, int age) { this->m_Name = Name; this->m_Age = age; }; string m_Name; int m_Age; }; void test() { // definition queue<Person> q; // data ready Person p1("A", 30); Person p2("B", 1000); Person p3("C", 900); Person p4("D", 800); cout << "size = " << q.size() << endl; // 入队 q.push(p1); q.push(p2); q.push(p3); q.push(p4); // 判断,查看 while (!q.empty()) { // head cout << "Name of head = " << q.front().m_Name << " "; // tail cout << "Name of tail = " << q.back().m_Name << endl; // 出队 q.pop(); } cout << "size = " << q.size() << endl; } int main() { test(); return 0; }
总结:
-
入队 —— push
-
出队 —— pop
-
队头 —— front
-
队尾 —— back
-
是否为空 —— empty
-
大小 —— size
2.6 list 容器
2.6.1 list 容器概念
功能:
-
将数据进行链式存储
链表 —— 一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
链表的组成:
-
一系列结点
结点的组成:
-
一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
STL中的链表是一个双向循环链表
由于链表的存储方式并不是连续的内存空间,因此链表list 中的迭代器只支持前移和后移,属于双向迭代器
list 的优点:
-
采用动态存储分配,不会造成内存浪费和溢出
-
链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
list 的缺点:
-
链表灵活,但是空间(指针域)和时间(遍历)额外消耗较大
List 的一个重要性质 —— 插入操作和删除操作都不会造成原有list 迭代器的失效,这在vector中并不成立
总结:
-
STL中List 和Vector 是两个最常被使用的容器,各有优劣
2.6.2 list 构造函数
功能描述:
-
创建list 容器
函数原型:
-
list<T> lst;
-
list(beg, end);
-
list(n, elem);
-
list(const list &lst);
示例:
#include <iostream> #include <list> #include "print.h" using namespace std; void test01() { // definition list<int>l1; // 添加数据 l1.push_back(10); l1.push_back(20); l1.push_back(30); l1.push_back(40); // 遍历链表 printList(l1); // scope list<int>l2(l1.begin(), l1.end()); printList(l2); // copy list<int>l3(l2); printList(l3); // n elems list<int>l4(10, 1000); printList(l4); } int main() { test01(); return 0; }
总结:
-
list 构造函数方法同其它几个STL常用容器,熟练掌握即可
2.6.3 list 赋值与交换
功能描述:
-
给list 容器进行赋值,以及交换list 容器
函数原型:
-
assign(beg, end);
-
assign(n, elem);
-
list& operator = (const list &lst);
-
swap(lst);
示例:
#include <iostream> #include <list> #include "print.h" using namespace std; // list 赋值 交换 void test01() { // definition list<int>l1; // 添加数据 l1.push_back(10); l1.push_back(20); l1.push_back(30); l1.push_back(40); printList(l1); // 赋值 list<int>l2; l2 = l1; printList(l2); list<int>l3; l3.assign(l2.begin(), l2.end()); printList(l3); list<int>l4; l4.assign(10, 100); printList(l4); } void test02() { // definition list<int>l1; // 添加数据 l1.push_back(10); l1.push_back(20); l1.push_back(30); l1.push_back(40); cout << "before: \n"; printList(l1); list<int>l2; l2.assign(10, 100); printList(l2); // 交换 cout << "after: \n"; l1.swap(l2); printList(l1); printList(l2); } int main() { // test01(); test02(); return 0; }
2.6.4 list 大小操作
功能描述:
-
对list 容器的大小进行操作
函数原型:
-
size();
-
empty();
-
resize(num);
-
resize(num, elem);
示例:
#include <iostream> #include <list> #include "print.h" using namespace std; // list 大小操作 void test01() { // definition list<int>l1; // 添加数据 l1.push_back(10); l1.push_back(20); l1.push_back(30); l1.push_back(40); printList(l1); // 判断 if (l1.empty()) { cout << "empty" << endl; } else { cout << "not empty" << endl; cout << "size = " << l1.size() << endl; } // 重新指定大小 l1.resize(10); printList(l1); l1.resize(3); printList(l1); } int main() { test01(); return 0; }
总结:
-
判断是否为空 —— empty
-
返回元素个数 —— size
-
重新指定个数 —— resize
2.6.5 list 插入和删除
功能描述:
-
对list 容器进行数据的插入和删除
函数原型:
-
push_back(elem);
-
pop_back();
-
push_front(elem);
-
pop_front();
-
insert(pos, elem);
-
insert(pos, n, elem)'
-
insert(pos, beg, end);
-
clear();
-
erase(beg, end);
-
返回下一个数据的位置
-
-
erase(pos);
-
返回下一个数据的位置
-
-
remove(elem);
-
删除容器中所有匹配 elem 的元素
-
示例:
#include <iostream> #include <list> #include "print.h" using namespace std; // list 插入与删除 void test01() { list<int>L; // 尾插 L.push_back(10); L.push_back(20); L.push_back(30); // 头插 L.push_front(100); L.push_front(200); L.push_front(300); printList(L); // 尾删 L.pop_back(); printList(L); // 头删 L.pop_front(); printList(L); // insert list<int>::iterator it = L.begin(); L.insert(L.begin(), 1000); printList(L); L.insert(it++, 2000); printList(L); // 删除 it = L.begin(); L.erase(++it); printList(L); // remove L.push_back(10000); L.push_back(10000); L.push_back(10000); printList(L); L.remove(10000); printList(L); // clear L.clear(); printList(L); } int main() { test01(); return 0; }
总结:
-
尾插 —— push_back
-
尾删 —— pop_back
-
头插 —— push_front
-
头删 —— pop_front
-
插入 —— insert
-
删除 —— erase
-
移除 —— remove
-
清空 —— clear
2.6.6 list 数据存取
功能描述:
-
对list 容器中数据进行存取
函数原型:
-
front();
-
返回第一个元素
-
-
back();
-
返回最后一个元素
-
示例:
#include <iostream> #include <list> #include "print.h" using namespace std; // list 数据存取 void test01() { list<int>L1; // 尾插 L1.push_back(10); L1.push_back(20); L1.push_back(30); L1.push_back(40); cout << "first = " << L1.front() << endl; cout << "back = " << L1.back() << endl; // 不能用L1[0] // 不能用L1.at(0) // 迭代器不支持 随机访问 // 验证 list<int>::iterator it = L1.begin(); it++; // 支持 it--; // 支持 // it = it + 1; 不支持 } int main() { test01(); return 0; }
总结:
-
list 容器中不可以通过[] 或者at 方式访问数据
-
返回第一个元素 —— front
-
返回最后一个元素 —— back
2.6.7 list 反转和排序
功能描述:
-
将容器中的元素反转,以及将容器中的数据进行排序
函数原型:
-
reverse();
-
反转链表
-
-
sort();
-
链表排序
-
示例:
#include <iostream> #include <list> #include <algorithm> #include "print.h" using namespace std; // list 反转 排序 void test01() { list<int>L1; L1.push_back(10); L1.push_back(50); L1.push_back(40); L1.push_back(90); printList(L1); // reverse L1.reverse(); cout << "reversed: \n"; // 90 40 50 10 printList(L1); } // 排序规则 bool myCompare(int v1, int v2) { // desc return v1 > v2; } void test02() { list<int>L1; L1.push_back(10); L1.push_back(50); L1.push_back(40); L1.push_back(90); cout << "before: \n"; printList(L1); // sort //sort(L1.begin(), L1.end()); // 错误,因为迭代器不支持随机访问 L1.sort(); cout << "sorted: \n"; // 10 40 50 90 默认升序 printList(L1); // 降序 L1.sort(myCompare); cout << "desc: \n"; // 90 50 40 10 printList(L1); } int main() { test01(); test02(); return 0; }
总结:
-
反转 —— reverse
-
排序 —— sort(成员函数)
2.7 set/multiset 容器:
2.7.1 set 基本概念
简介:
-
所有元素都会在插入时自动被排序
本质:
-
set/multiset 属于关联式容器,底层结构是用二叉树实现
set和multiset 区别:
-
set不允许容器中有重复的元素
-
multiset允许容器中有重复的元素
2.7.2 set 构造和赋值
功能描述:
-
创建set 容器以及赋值
构造:
-
set<T> st;
-
默认构造函数
-
-
set(const set &st);
-
拷贝构造函数
-
赋值:
-
set& operator = (const set &st);
示例:
#include <iostream> #include <set> #include "print.h" using namespace std; void test01 () { set<int>s1; // 插入 只有insert方法 s1.insert(10); s1.insert(40); s1.insert(30); s1.insert(20); s1.insert(30); // 遍历容器 set容器默认自动无重复、排序遍历 printSet(s1); // 拷贝构造 set<int>s2(s1); printSet(s2); // 赋值操作 set<int>s3; s3 = s2; printSet(s3); } int main() { test01(); return 0; }
总结:
-
set 容器插入数据时用insert
-
set 容器插入数据的数据会自动排序
2.7.3 set 大小和交换
功能描述:
-
统计set 容器大小以及交换set 容器L
函数原型:
-
size();
-
empty();
-
swap(st);
示例:
#include <iostream> #include <set> #include "print.h" using namespace std; // 大小 void test01 () { set<int>s1; // 插入 INSERT s1.insert(10); s1.insert(40); s1.insert(30); s1.insert(20); s1.insert(30); // 打印容器 printSet(s1); // empty? if (s1.empty()) { cout << "empty" << endl; } else { cout << "size = " << s1.size() << endl; } } // 交换 void test02() { set<int>s1; set<int>s2; // 插入 INSERT s1.insert(10); s1.insert(40); s1.insert(30); s1.insert(20); s2.insert(100); s2.insert(400); s2.insert(300); s2.insert(200); printSet(s1); printSet(s2); // swap cout << "swapped: \n"; s1.swap(s2); printSet(s1); printSet(s2); } int main() { // test01(); test02(); return 0; }
总结:
-
统计大小 —— size
-
判断是否为空 —— empty
-
交换容器 —— swap
2.7.4 set 插入和删除
功能描述:
-
set 容器进行插入数据和删除数据
函数原型:
-
insert(elem);
-
clear();
-
erase(pos);
-
返回下一个元素的迭代器
-
-
erase(beg, end);
-
返回下一个元素的迭代器
-
-
erase(elem);
-
删除容器中值为elem 的元素
-
示例:
#include <iostream> #include <set> #include "print.h" using namespace std; // 插入和删除 void test01 () { set<int>s1; // insert s1.insert(30); s1.insert(10); s1.insert(20); s1.insert(30); // traversal printSet(s1); // delete s1.erase(s1.begin()); printSet(s1); // 删除重载版本 s1.erase(30); printSet(s1); // 清空 s1.erase(s1.begin(), s1.end()); printSet(s1); s1.clear(); printSet(s1); } int main() { test01(); return 0; }
总结:
-
插入 —— insert
-
删除 —— erase
-
清空 —— clear
2.7.5 set 查找和统计
功能描述:
-
对 set 容器进行查找以及统计数据
函数原型:
-
find(key);
-
查找key 是否存在。存在则返回对应迭代器,否则返回set.end()
-
-
count(key);
-
统计set 的元素个数
-
示例:
#include <iostream> #include <set> #include "print.h" using namespace std; // 查询 和 统计 void test01 () { set<int>s1; // insert s1.insert(30); s1.insert(10); s1.insert(20); s1.insert(30); printSet(s1); // find set<int>::iterator pos = s1.find(200); if (pos != s1.end()) { cout << "found: " << *pos << endl; } else { cout << "not found" << endl; } // count 对于set 统计的结果仅限于 0 和 1 int num = s1.count(30); cout << "num = " << num << endl; } int main() { test01(); return 0; }
总结:
-
查找 —— find (返回的是迭代器)
-
统计 —— count (对于set,结果为0 或 1)
2.7.6 set和 multiset 区别
区别:
-
set 不可以插入重复的数据,而multiset 可以
-
set 插入数据的同时会返回插入结果,表示插入是否成功
-
multiset 不会检测数据,因此可以插入重复数据
示例:
#include <iostream> #include <set> #include "print.h" using namespace std; // set 和 multiset 的区别 void test01 () { set<int>s; // 对组 pair<set<int>::iterator, bool> ret = s.insert(10); if (ret.second) { cout << "first success" << endl; } else { cout << "first fail" << endl; } ret = s.insert(10); if (ret.second) { cout << "second success" << endl; } else { cout << "second fail" << endl; } // multiset 可重复 multiset<int>ms; ms.insert(10); ms.insert(10); ms.insert(10); printMultiset(ms); } int main() { test01(); return 0; }
总结:
-
若不允许插入重复数据,则使用set
-
若允许插入重复数据,则使用multiset
2.7.7 pair 对组创建
功能描述:
-
成对出现的数据,利用对组可以返回两个数据
两种创建方式:
-
pair<type, type> p(val1, val2);
-
pair<type, type> p = make_pair(val1, val2);
示例:
#include <iostream> using namespace std; // pair void test01 () { // 1 pair<string, int> p("Tom", 90); cout << "name: " << p.first << ", age: " << p.second << endl; // 2 pair<string, int> p1 = make_pair("alan", 20); cout << "name: " << p1.first << ", age: " << p1.second << endl; } int main() { test01(); return 0; }
总结:
-
两种方式都可以创建对组。
2.7.8 set 容器排序
主要技术点:
-
利用仿函数,改变排序规则
示例1 —— set 存放内置数据类型
#include <iostream> #include <set> #include "print.h" using namespace std; // sorting rule class myCompare { public: // 具有类型“XXX”的表达式会丢失一些 const-volatile 限定符以调用“XXX” 此时可以在函数体前添加const 限定符 bool operator()(int v1, int v2) const{ return v1 > v2; } }; // set 内置排序 void test () { // 指定排序规则 desc set<int, myCompare>s; // 第二参数为 一个类 s.insert(10); s.insert(40); s.insert(20); s.insert(50); s.insert(30); for (set<int, myCompare>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } int main() { test(); return 0; }
总结:
-
利用仿函数可以指定set 容器的排序规则
示例2 —— set 存放自定义数据类型
#include <iostream> #include <set> #include "print.h" using namespace std; // self-definition class Person { public: string m_Name; int m_Age; Person(string name, int age) { this->m_Name = name; this->m_Age = age; } }; // 自定义数据类型 必须指定排序规则 class comparePerson { public: bool operator() (const Person p1, const Person p2) const{ return p1.m_Age > p2.m_Age; } }; // 存放自定义数据来下 void test() { set<Person, comparePerson>s; // 创建对象 Person p1("a", 24); Person p2("b", 28); Person p3("c", 25); Person p4("d", 21); // insert s.insert(p1); s.insert(p2); s.insert(p3); s.insert(p4); // traversal for (set<Person, comparePerson>::iterator it = s.begin(); it != s.end(); it++) { cout << "Name: " << it->m_Name << " , age: " << it->m_Age << endl; } } int main() { test(); return 0; }
总结:
-
对于自定义数据类型,set 必须指定排序规则才可以插入数据
2.8 map/multimap 容器
2.8.1 map 基本概念
简介:
-
map 中所有元素都是pair
-
pair 中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
-
所有元素都会根据元素的键值自动排序
本质:
-
关联式容器,底层结构用二叉树实现
优点:
-
可以根据key 值快速找到value 值
map与 multimap 的区别:
-
map 不允许容器中有重复key值元素
-
multimap允许容器中有重复key值元素
2.8.2 map 构造和赋值
功能描述:
-
对map 容器进行构造和赋值操作
函数原型:
构造:
-
map(T1, T2) mp;
-
map(const map &mp);
赋值:
-
map& operator = (const map &mp);
示例:
#include <iostream> #include <map> #include "print.h" using namespace std; // map 构造和赋值 void test() { // definition map<int, int>m; // insert m.insert(pair<int, int>(1, 10)); m.insert(pair<int, int>(3, 30)); m.insert(pair<int, int>(2, 20)); m.insert(pair<int, int>(4, 40)); // traversal 按照key 值自动升序排序 printMap(m); // copy construction 拷贝构造 map<int, int>m2(m); printMap(m2); // assignment map<int, int>m3; m3 = m2; printMap(m3); } int main() { test(); return 0; }
总结::
-
map 中所有元素都是成对出现,插入数据时要使用对组
2.8.3 map 大小和交换
功能描述:
-
统计map 容器大小以及交换map 容器
函数原型:
-
size();
-
empty();
-
swap(st);
-
交换两个集合容器
-
示例:
#include <iostream> #include <map> #include "print.h" using namespace std; // map 大小和被交换 // size void test01() { // definition map<int, int>m; // insert m.insert(pair<int, int>(1, 10)); m.insert(pair<int, int>(3, 30)); m.insert(pair<int, int>(2, 20)); m.insert(pair<int, int>(4, 40)); if (m.empty()) { cout << "empty" << endl; } else { cout << "not empty" << endl; cout << "size = " << m.size() << endl; } } // swap void test02() { // definition map<int, int>m1; map<int, int>m2; // insert m1.insert(pair<int, int>(1, 10)); m1.insert(pair<int, int>(3, 30)); m1.insert(pair<int, int>(2, 20)); m1.insert(pair<int, int>(4, 40)); m2.insert(pair<int, int>(1, 100)); m2.insert(pair<int, int>(3, 300)); m2.insert(pair<int, int>(2, 200)); m2.insert(pair<int, int>(4, 400)); // swap cout << "before:\n"; printMap(m1); printMap(m2); cout << "after:\n"; m1.swap(m2); printMap(m1); printMap(m2); } int main() { test01(); test02(); return 0; }
总结:
-
统计大小 —— size
-
判断是否为空 —— empty
-
交换容器 —— swap
2.8.4 map 插入和删除
功能描述:
-
map 容器进行插入和删除数据
函数原型:
-
insert(elem);
-
clear();
-
erase(pos);
-
erase(beg, end);
-
erase(key);
-
删除容器中值为key 的元素
-
示例:
#include <iostream> #include <map> #include "print.h" using namespace std; // map 插入 和 删除 void test01() { // definition map<int, int>m; // insert 1 m.insert(pair<int, int>(1, 10)); // insert 2 m.insert(make_pair(2, 20)); // insert 3 m.insert(map<int, int>::value_type(3, 30)); // insert 4 not recommended 主要利用key来访问value m[4] = 40; // key: 5, value: 0 //cout << m[5] << endl; printMap(m); // erase --- according to key m.erase(m.begin()); printMap(m); m.erase(3); printMap(m); m.erase(m.begin(), m.end()); printMap(m); // clear m.clear(); printMap(m); } int main() { test01(); return 0; }
总结:
-
插入 —— insert
-
删除 —— erase
-
清空 —— clear
2.8.5 map 查找和统计
功能描述:
-
对map 容器进行数据查找以及统计数据
函数原型:
-
find(key);
-
若存在,返回该键对应的迭代器;若不存在,返回set.end();
-
-
count(key);
-
统计key 元素的个数
-
示例:
#include <iostream> #include <map> #include "print.h" using namespace std; // map 查找 和 统计 void test01() { // find map<int, int>m; m.insert(make_pair(1, 10)); m.insert(make_pair(2, 20)); m.insert(make_pair(3, 30)); // m.insert(make_pair(3, 40)); 不允许插入重复键值 map<int, int>::iterator pos = m.find(3); if (pos != m.end()) { cout << "found, key = " << (*pos).first << ", val = " << pos->second << endl; } else { cout << "not found" << endl; } // statistics int num = m.count(3); cout << "num = " << num << endl; } int main() { test01(); return 0; }
总结:
-
查找 —— find(返回迭代器)
-
统计 —— count(对于map, 结果为0 或 1)
2.8.6 map 容器排序
主要技术点:
-
利用仿函数,客户以改变排序规则
示例:
#include <iostream> #include <map> #include "print.h" using namespace std; class my { public: bool operator()(int v1, int v2) const { return v1 > v2; } }; void test01() { map<int, int, my>m; m.insert(make_pair(1, 10)); m.insert(make_pair(2, 20)); m.insert(make_pair(3, 30)); m.insert(make_pair(4, 40)); m.insert(make_pair(5, 50)); // desc for (map<int, int, my>::iterator it = m.begin(); it != m.end(); it++) { cout << "key: " << it->first << ", val: " << it->second << endl; } cout << endl; } int main() { test01(); return 0; }
总结:
-
利用仿函数可以指定map 容器的排序规则
-
对于自定义数据类型,map 必须指定排序规则,同set 容器