目录

一、简介

1.1 STL 具有两个特点

1.2 举一个数组对比 STL 的例子,以说明STL特点和优势

1.3 STL中六大组件

1.4 C++ STL头文件

二、容器

三、序列式容器

3.1 序列式容器对比(部分)

3.2 vector(向量)容器

3.2.1 定义方法

3.2.2基本函数实现

3.2.3 实践

四、关联式容器

4.1 关联式容器对比

4.1.1 set和map的特性、区别

4.2 map容器

4.2.1 定义方法

4.2.2 基本操作函数

4.2.3 实践

附录:摘录及参考资料


本文的目标是:在没有STL学习基础的情况下,快速了解vector和map两个容器的定义和使用。主要介绍了STL定义、组件,STL组件中容器的分类及其特点,并进一步引出vector容器和map容器,介绍了它们的基本特点和使用方法。

一、简介

STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库。它被容纳于C++标准程序库(C++ Standard Library)中,是ANSI/ISO C++标准中最新的也是极具革命性的一部分。其包含有大量的模板类和模板函数,是 C++ 提供的一个基础模板的集合,用于完成诸如输入/输出、数学计算等功能。

1.1 STL 具有两个特点

一是数据结构和算法的分离,二是不是面向对象的。

数据结构和算法的分离。使得STL变得非常通用。例如,由于STL的sort()函数是完全通用的,你可以用它来操作几乎任何数据集合,包括链表,容器和数组。

不是面向对象的。为了具有足够通用性,STL主要依赖于模板,而不依赖封装、继承、虚函数(面向对象编程的三要素)。使得STL的组件具有广泛通用性的底层特征。另外,由于STL是基于模板,内联函数的使用使得生成的代码短小高效。

1.2 举一个数组对比 STL 的例子,以说明STL特点和优势

在 C++ 中如果定义一个数组,可采用:

int a[n];

这种定义数组的方法需要事先确定好数组的长度,即 n 必须为常量,这意味着,如果在无法确定数组长度,就需要将数组长度设为可能的最大值,导致存储空间的浪费。

当然,还可以采用在堆空间中动态申请内存的方法,根据变量n动态申请内存,防止存储空间浪费的问题。但是,如果程序执行过程中出现空间不足的情况时,则需要加大存储空间,将原内存空间的数据全部复制到新申请的内存空间中,并将原来的堆空间释放:

int *p = new int[n];...//发现空间不足
int * temp = new int[m];
memecpy(temp, p, sizeof(int)*n));
delete [] p; p = temp;

而完成相同的操作,如果采用 STL 标准库,则会简单很多,因为大多数操作细节将不需要程序员关心。下面是使用向量模板类 vector 实现以上功能的示例:

vector <int> a; //定义a数组,当前数组长度为0。//向数组a中添加 10 个元素,a可以根据存储数据的数量自动变长。
for (int i = 0; i < 10 ; i++)
{    a.push_back(i);
}//可以手动调整数组 a 的大小
a.resize(100);
a[90] = 100;//可以直接删除数组 a 中所有的元素,a的长度变为0。
a.clear();//重新调整 a 的大小为 20,并存储 20 个 -1 元素。
a.resize(20, -1);

对比以上两种使用数组的方式不难看出,使用 STL 可以更加方便灵活地处理数据。所以,大家只需要系统地学习 STL,便可以集中精力去实现程序的功能,而无需再纠结某些细节如何用代码实现。

1.3 STL中六大组件

容器(Container):一些封装数据结构的模板类,如list列表容器,vector向量容器,deques等。为了访问容器中的数据,可以使用由容器类输出的迭代器。

迭代器(Iterator):提供了访问容器中对象的方法,如同指针。对容器中数据的读和写,是通过迭代器完成的。事实上,C++的指针也是一种迭代器。迭代器也可以是那些定义了operator*(),或定义了类似于指针操作符方法的类对象;

算法(Algorithm):是用来操作容器中的数据的模板函数。例如,STL用sort()来对一个vector中的数据进行排序,用find()来搜索一个list中的对象,函数本身与他们操作的数据的结构和类型无关,因此他们可以在从简单数组到高度复杂容器的任何数据结构上使用。这些算法在 std 命名空间中定义,其中大部分算法都包含在头文件 <algorithm> 中,少部分位于头文件 <numeric> 中。

函数对象(Functor):如果一个类将()运算符重载为成员函数,这个类就称为函数对象类,这个类的对象就是函数对象(又称仿函数)。

适配器(Adaptor):可以使一个类的接口(模板的参数)适配成用户指定的形式,从而让原本不能在一起工作的两个类工作在一起。值得一提的是,容器、迭代器和函数都有适配器。

分配器(allocator):为容器类模板提供自定义的内存申请和释放功能,由于往往只有高级用户才有改变内存分配策略的需求,因此内存分配器对于一般用户来说,并不常用。

其中,迭代器、函数对象、适配器、内存分配器这4部分是为容器、算法服务的。但是,STL最重要的是要理解前三个组件:容器、迭代器、算法。

1.4 C++ STL头文件

迭代器头文件:<iterator>

算法头文件:<algorithm>

序列式容器头文件:<vector>、<deque>、<list>、<queue>、<stack>

关联式容器头文件:<set>、<map>

无序关联式容器:<unordered_set>、<unordered_map>

其它:<functional>、<numeric>、<memory>、<utility>

按照 C++ 标准库的规定,所有标准头文件都不再有扩展名。以 <vector> 为例,此为无扩展名的形式,而 <vector.h> 为有扩展名的形式。

二、容器

它就是一些模板类的集合,但和普通模板类不同的是,容器中封装的是组织数据的方法(也就是数据结构)。

容器类型是可用于创建具体容器对象的模板。以前有11个容器类型:deque、list、queue、priority_queue、stack、vector、map、multimap、set、multiset、bitest。C++11新增了5种容器类型:forward_list、unordered_map、unordered_multimap、unordered_set、unordered_multiset,并且不将bitset视为容器,而将其视作一种独立的类别。

因此,除了bitset之外,目前共有15种容器类型,他们又可以分为3个大的种类,分别是:序列式容器(sequence containers)、关联式容器(associative containers)、无序关联式容器(哈希容器)。大概介绍为:

(1)序列式容器(sequence containers)

序列式容器共包括7个类型的容器:vector、deque、list、forward_list、queue、priority_queue、stack。

之所以被称为序列容器,是因为它们都以线性排列(类似普通数组的存储方式)来存储某一指定类型(例如int、double等)的数据,且元素在容器中的位置同元素的值无关,即容器不是排序的。将元素插入容器时,指定在什么位置,元素就会位于什么位置。

(2)关联式容器(associative containers)

关联式容器提供了4个类型的容器:set、multiset、map、multimap。

使用关联式容器存储的元素,都是一个一个的“键值对”( <key,value> )。排序容器中的元素默认是由小到大排序好的,即便是插入元素,元素也会插入到适当位置。所以关联容器在查找时具有非常好的性能。

(3)无序关联式容器(哈希容器)。

无序关联式容器提供了4个具体的容器:unordered_map、unordered_multimap、unordered_set、unordered_multiset。

它们都是C++11才引入到STL标准库中的。和排序容器不同,无序关联式容器中的元素是未排序的,元素的位置由哈希函数确定。无序关联式容器擅长通过指定键查找对应的值。

这3类容器的存储方式完全不同,因此使用不同容器完成相同操作的效率也大不相同。所以在实际使用时,要善于根据想实现的功能,选择合适的容器。

三、序列式容器

3.1 序列式容器对比(部分)

序列式容器有7种,这里我们比较它们其中的4种:

vector<T>(向量容器):用来存放 T 类型的元素,是一个长度可变的序列容器,即在存储空间不足时,会自动申请更多的内存。使用此容器,在尾部增加或删除元素的效率最高(时间复杂度为 O(1) 常数阶),在其它位置插入或删除元素效率较差(时间复杂度为 O(n) 线性阶,其中 n 为容器中元素的个数);

deque<T>(双端队列容器):和 vector 非常相似,区别在于使用该容器不仅尾部插入和删除元素高效,在头部插入或删除元素也同样高效,时间复杂度都是 O(1) 常数阶,但是在容器中某一位置处插入或删除元素,时间复杂度为 O(n) 线性阶;

list<T>(链表容器):是一个长度可变的、由 T 类型元素组成的序列,它以双向链表的形式组织元素,在这个序列的任何地方都可以高效地增加或删除元素(时间复杂度都为常数阶 O(1)),但访问容器中任意元素的速度要比前三种容器慢,这是因为 list<T> 必须从第一个元素或最后一个元素开始访问,需要沿着链表移动,直到到达想要的元素。

forward_list<T>(正向链表容器):和 list 容器非常类似,只不过它以单链表的形式组织元素,它内部的元素只能从第一个元素开始访问,是一类比链表容器快、更节省内存的容器。

3.2 vector(向量)容器

vector 容器是 STL 中最常用的容器之一,是对 C++ 普通数组的“升级版”。 vector 实现的是一个动态数组,即可以进行元素的插入和删除,在此过程中,vector 会(通过new和delete)动态调整所占用的内存空间,整个过程无需人工干预。

因为该容器擅长在尾部插入或删除元素,在常量时间内就可以完成,时间复杂度为O(1);而对于在容器头部或者中部插入或删除元素,则花费时间要长一些(移动元素需要耗费时间),时间复杂度为线性阶O(n)。

3.2.1 定义方法

std::vector<int> a1;               //1个元素,默认初始值为0
std::vector<int> a2(10);           //10个元素,默认初始值为0
std::vector<int> a3 {2, 3, 5, 7};  //4个元素,指定元素值
std::vector<int> a4(10, 100);      //10个元素,默认初始值重新指定为100int num = 20;
double value = 1.0;
std::vector<double> a5(num, value) //可以用变量指定元素个数和初始值等信息std::vector<char> a6_temp(5, 'c');
std::vector<char> a6(a6_temp);      //用其它元素类型相同的vector,创建新的vector容器。int arr[] = {1, 2, 3, 4, 5};
std::vector<int> a7(arr, arr+3);   //a7将保存{1, 2, 3}std::vector<int> a8_temp {2, 3, 5, 7, 11, 13};
std::vector<int> a8(std::begin(a8_temp), std::end(a8_temp)-2); //a8将保存{2, 3, 5, 7}

3.2.2基本函数实现

(1) 构造函数

vector():创建一个空vector

vector(int nSize):创建一个vector,元素个数为nSize

vector(int nSize,const T& t):创建一个vector,元素个数为nSize,且元素值均为t

vector(const vector&):复制构造函数

vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中

(2) 增加函数

void push_back(const T& x):向量尾部增加一个元素X

iterator insert(iterator it,const T& x):向量中迭代器指向元素前增加一个元素x

iterator insert(iterator it,int n,const T& x):向量中迭代器指向元素前增加n个相同的元素x

iterator insert(iterator it,const_iterator first,const_iterator last):向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据

(3) 删除函数

iterator erase(iterator it):删除向量中迭代器指向元素

iterator erase(iterator first,iterator last):删除向量中[first,last)中元素

void pop_back():删除向量中最后一个元素

void clear():清空向量中所有元素

(4) 遍历函数

reference at(int pos):返回pos位置元素的引用

reference front():返回首元素的引用

reference back():返回尾元素的引用

iterator begin():返回向量头指针,指向第一个元素

iterator end():返回向量尾指针,指向向量最后一个元素的下一个位置

reverse_iterator rbegin():反向迭代器,指向最后一个元素

reverse_iterator rend():反向迭代器,指向第一个元素之前的位置

(5) 判断函数

bool empty() const:判断向量是否为空,若为空,则向量中无元素

(6) 大小函数

int size() const:返回向量中元素的个数

int capacity() const:返回当前向量张红所能容纳的最大元素值

int max_size() const:返回最大可允许的vector元素数量值

(7) 其他函数

void swap(vector&):交换两个同类型向量的数据

void assign(int n,const T& x):设置向量中第n个元素的值为x

void assign(const_iterator first,const_iterator last):向量中[first,last)中元素设置成当前向量元素

3.2.3 实践

(1)基本函数操作

/*************************************************************************> File Name: vector_1.cpp> Author: hank> Mail: 34392195@qq.com > Created Time: 2020年08月07日 星期五 05时27分21秒************************************************************************/#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int main(int argc, char *argv[])
{
//1 创建并初始化vectorvector<int> obj{2, 3, 4, 15, 1, 7, 3};    //2-1 遍历方法1(size()数据个数)cout << "两种遍历方法:" << endl;for(int i = 0; i < obj.size(); i++)//size()容器中实际数据个数 {cout<< obj[i] <<" ";}cout << endl;//2-2 遍历方法2(使用迭代器)vector<int>::iterator iter;for(iter = obj.begin(); iter != obj.end(); iter++){cout << *iter << " ";}cout << endl;cout << endl;//3-1 从小到大排序(sort(),需要<algorithm>算法头文件)obj.push_back(5); //插入obj.push_back(3); //插入cout << "添加两个数据:" << endl;for(iter = obj.begin(); iter != obj.end(); iter++){cout << *iter << " ";}cout << endl << endl;sort(obj.begin(), obj.end());//sort()排序cout << "sort()排序后:" << endl;for(iter = obj.begin(); iter != obj.end(); iter++){cout << *iter << " ";}cout << endl;//3-2 从大到小排序(reverse(),需要<algorithm>算法头文件)  reverse(obj.begin(), obj.end()); //reverse()排序cout << "reverse()排序后:" << endl;for(iter = obj.begin(); iter != obj.end(); iter++){cout << *iter << " ";}cout << endl << endl;//4 删除(pop_back() 尾删)for(int i = 0; i < 4; i++) {obj.pop_back();}cout << "删除4个元素后:" << endl;for(iter = obj.begin(); iter != obj.end(); iter++){cout << *iter << " ";}cout << endl << endl;//6 清空(clear())obj.clear();cout << "清空后:" << endl;for(iter = obj.begin(); iter != obj.end(); iter++){cout << *iter << " ";}cout << endl;return 0;
}

编译执行:

(2)C++ Primer Plus P683 程序清单16.9 vect3.app源代码

/*************************************************************************> File Name: vector_2.cpp> Author: hank> Mail: 34392195@qq.com > Created Time: 2020年07月28日 星期二 20时27分51秒************************************************************************/#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;struct Review
{string title;int rating;
};//function1: 升序-sort版本1,运算符<重载多实现
bool operator<(const Review &r1, const Review &r2)
{if(r1.title < r2.title)return true;else if(r1.title == r2.title && r1.rating < r2.rating)return true;elsereturn false;
}//function2: 降序-sort版本2,定义函数对象
bool worseThan(const Review &r1, const Review &r2)
{if(r1.rating > r2.rating)return true;elsereturn false;
}//function3: 输入数据
bool FillReview(Review &rr)
{//rr.titlecout << "Enter book title (enter \"quit\" to quit): ";getline(cin, rr.title);if(rr.title == "quit"){return false;}//rr.ratingcout << "Enter book rating: ";cin >> rr.rating;if(!cin){return false;}//clear input buffwhile(cin.get() != '\n') {continue;}return true;
}//function4: 遍历打印
void ShowReview(const Review &rr)
{cout << rr.rating << "\t" << rr.title << endl;
}//**auto input
vector<Review> auto_FillReview(vector<Review> books)
{Review temp;temp.title = "The Cat Who Can Teach You Weight Loss";temp.rating = 8;books.push_back(temp);temp.title = "The Dogs of Dharma";temp.rating = 6;books.push_back(temp);temp.title = "The Wimps of Wonk";temp.rating = 3;books.push_back(temp);temp.title = "Farewell and Delete";temp.rating = 7;books.push_back(temp);return books;
}//main
int main()
{vector<Review> books;Review temp;//input data untile input "quit"
#if 0/* 书上code,终端输入数据 */while (FillReview(temp))books.push_back(temp);
#else/* 写定函数,自动输入 */books = auto_FillReview(books);
#endifif (books.size() > 0){//original datascout << "Thank you. You entered the following "<< books.size() << " ratings:\n"<< "Rating\tBook\n";for_each(books.begin(), books.end(), ShowReview);cout << endl;//sort by title, ascendingsort(books.begin(), books.end());cout << "Sort by title:\n" <<"Rating\tBook\n";for_each(books.begin(), books.end(), ShowReview);cout << endl;//sort by rating, descendingsort(books.begin(), books.end(), worseThan);cout << "Sort by rating:\n"<<"Rating\tBook\n";for_each(books.begin(), books.end(),ShowReview);cout << endl;//randomrandom_shuffle(books.begin(), books.end());cout << "After shuffling:\n"<< "Rating\ttitle\n";for_each(books.begin(), books.end(), ShowReview);}else{cout << "No entries! Bye!" << endl;}return 0;}

编译执行:

四、关联式容器

关联是容器再存储元素值的同时,还会为各个元素再配备一个“键”(Key)值。key的功能是在使用关联式容器的过程中,如果查找的目标元素的键值已知,就可以通过键值直接找到该元素,无需再遍历整个容器。

相比于序列式容器,选用关联式容器往往是因为,关联式容器可以快速查找、读取或者删除所存储的元素。同时,插入元素的效率也比序列式容器高。除此之外,序列式容器中存储的元素默认都是未经过排序的,而使用关联式容器存储的元素,默认会键值升序排序

注意,关联式容器所具备的这些特性,归咎于 STL 标准库在实现该类型容器时,底层选用了 「红黑树」这种数据结构来组织和存储各个键值对。

4.1 关联式容器对比

C++ STL 标准库提供了4种关联式容器,分别为 map、set、multimap、multiset。

表4.1 关联式容器特点对比
容器名称 特点
set 定义在 <set> 头文件中,使用该容器存储的数据,各个元素键和值完全相同且各个元素的值不能重复(保证了各元素键的唯一性)。该容器会自动根据各个元素的键(其实也就是元素值)的大小进行升序排序(调用 std::less<T>)。
multiset 定义在 <set> 头文件中,和 set 容器唯一的不同在于,multiset 容器中存储元素的值可以重复(一旦值重复,则意味着键也是重复的)。
map 定义在 <map> 头文件中,使用该容器存储的数据,其各个元素的键必须是唯一的(即不能重复),该容器会根据各元素键的大小,默认进行升序排序(调用 std::less<T>)。
multimap 定义在 <map> 头文件中,和 map 容器唯一的不同在于,multimap 容器中存储元素的键可以重复。

4.1.1 set和map的特性、区别

set特性:

  • set中的元素键值和实值相同,即value就是key
  • 不允许出现键值重复(multiset允许键值重复)
  • 所有的元素都会被自动排序(升序)
  • 不能通过迭代器来改变set的值,因为set的值就是键
  • 搜索、移除和插入拥有对数复杂度
  • 当对容器中的元素进行插入或者删除时,操作之前的所有迭代器在操作之后依然有效。
  • set集合中的元素为结构体或自定义类时,该结构体或自定义类必须实现运算符‘<’的重载。

map特性:

  • map中的元素键值和实值可以不相同
  • 和set一样,map中不允许出现键值重复(multimap允许键值重复)(因此,map支持[ ]运算符,multimap不支持[ ]运算符)
  • 和set一样,所有的元素都会通过键值自动排序(升序)
  • map的键是不能修改的,但是其键对应的值是可以修改的。

map和set一样是关联式容器,它们的底层容器都是红黑树,区别就在于map的值不作为键,键和值是分开的,而set键和值相同。

4.2 map容器

map 由红黑树实现,其元素都是 “键/值” 所形成的一个对组(key/value pairs)。每个元素有一个键,一个键只能出现一次,不允许重复。 map 内部所有元素按照“键”自动排序。

map 主要用于键和值一对一映射的情况,比如一个班级中,每个学生的学号跟他的姓名就存在着一对一映射的关系。

根据 key 值快速查找记录,查找的复杂度基本是 O(logN),如果有 1000 个记录,二分查找最多查找 10次(1024)。增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。

4.2.1 定义方法

std::map<std::string, int>a1;  //调用构造函数
std::map<std::string, int>a2{{"string 1",10},{"string 2",20}};  //初始化
std::map<std::string, int>a3{std::make_pair("string 1",10),std::make_pair("string 2",20)}; //map容器中存储的键值对,本质是pair类模板创建的pair对象。std::map<std::string, int>temp_a4;
std::map<std::string, int>a4(temp_a4); //map拷贝构造函数std::map<std::string, int>fun_makeMap() //移动构造函数,C++11标准中
{std::map<std::string, int>temp_a5{{“string 1”, 10}, {"string 2", 20}};return temp_a5;
}
std::map<std::string, int>a5(fun_makeMap());//取已建map容器中指定区域内的键值对,创建并初始化map容器
//这里初始化了一个{“string 2”, 20}键值对的容器
std::map<std::string, int>temp_a6{{"string 1", 10}, {"string 2", 20}};
std::map<std::string, int>a6(++temp_a6.begin(), temp_a6.end());//修改map容器排序规则
//    第一个调用std::less<T>为升序排序。(这是默认规则)
//    第二个调用std::greater<std::string>为降序排序。
std::map<std::string, int, std::less<std::string> >a7_1{{"string 1", 10}, {string2, 20}}
std::map<std::string, int, std::greater<std::string> >a7_2{{"string 1", 10}, {"string 2", 20}};

4.2.2 基本操作函数

begin():返回指向map头部的迭代器。返回指向容器中第一个(注意,是已排好序的第一个)键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。

end():返回指向map末尾的迭代器。返回指向容器最后一个元素(注意,是已排好序的最后一个)所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。

rbegin():返回一个指向map尾部的逆向迭代器。返回指向最后一个(注意,是已排好序的最后一个)元素的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。

rend():返回一个指向map头部的逆向迭代器。返回指向第一个(注意,是已排好序的第一个)元素所在位置前一个位置的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。

cbegin():和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。

cend():和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。

crbegin():和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。

crend():和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。

find(key):查找一个元素。在 map 容器中查找键为 key 的键值对,如果成功找到,则返回指向该键值对的双向迭代器;反之,则返回和 end() 方法一样的迭代器。另外,如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。

lower_bound(key):返回键值>=给定元素的第一个位置。返回一个指向当前 map 容器中第一个大于或等于 key 的键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。

upper_bound(key):返回键值>给定元素的第一个位置。返回一个指向当前 map 容器中第一个大于 key 的键值对的迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。

equal_range(key):该方法返回一个 pair 对象(包含 2 个双向迭代器),其中 pair.first 和 lower_bound() 方法的返回值等价,pair.second 和 upper_bound() 方法的返回值等价。也就是说,该方法将返回一个范围,该范围中包含的键为 key 的键值对(map 容器键值对唯一,因此该范围最多包含一个键值对)。

empty() :如果map为空则返回true;否则 false。

max_size():返回可以容纳的最大元素个数

size():返回map中元素的个数

at(key):找到 map 容器中 key 键对应的值,如果找不到,该函数会引发 out_of_range 异常。

insert():插入元素,插入键值对。

emplace():在当前 map 容器中的指定位置处构造新键值对。其效果和插入键值对一样,但效率更高。c++11

erase():删除一个元素。删除 map 容器指定位置、指定键(key)值或者指定区域内的键值对。

clear():删除所有元素。清空 map 容器中所有的键值对,即使 map 容器的 size() 为 0。

swap():交换两个map。这要求操作的 2 个键值对的类型必须相同。

count():返回指定元素出现的次数。

get_allocator():返回map的配置器。

key_comp():返回比较元素key的函数。

value_comp():返回比较元素value的函数。

4.2.3 实践

使用一些基本的方法,完成一些操作。

/*************************************************************************> File Name: map1.cpp> Author: hank> Mail: 34392195@qq.com > Created Time: 2020年08月05日 星期三 01时22分24秒************************************************************************/#include <iostream>
#include <map>
#include <string>
using namespace std;int main(int argc, char *argv[])
{
//1.定义map<int, string, greater<int>> id_name; //greater:倒序map<int, string>::iterator iter;//迭代器//2.插入
#if 0// 插入单个键值对,并返回插入位置和成功标志,插入位置已经存在值时,插入失败pair<iterator,bool> insert (const value_type& val);//在指定位置插入,在不同位置插入效率是不一样的,因为涉及到重排iterator insert (const_iterator position, const value_type& val);// 插入多个void insert (InputIterator first, InputIterator last);//c++11开始支持,使用列表插入多个   void insert (initializer_list<value_type> il);
#endifid_name.insert(pair<int, string>(27, "Hank"));                //插入pair数据id_name.insert(map<int, string>::value_type(0, "Baby"));  //插入value_type数据id_name.emplace(28, "Leiney");            pair<map<int, string>::iterator, bool> ret;ret = id_name.insert(map<int, string>::value_type(0, "another Baby"));  //插入  c++11if(ret.second == false){cout << "element '0' alread existed, with a value of " << ret.first->second << endl;cout << endl;  }//列表形式插入map<int, string> id_name2; id_name2.insert({{22, "laoluo"}, {37, "laoguo"}});//数组形式插入,id自动生成,从1开始map<int, string> id_name3;id_name3[1] = "jiaojiao";id_name3[2] = "xiaoming";id_name3[3] = "xiaohui";//3.大小cout << "size(id_name) = " << id_name.size() << endl;cout << endl;//4.判空,迭代器遍历if(id_name.empty()){cout << "map is empty!" << endl;}else{for(iter = id_name.begin(); iter != id_name.end(); iter++){cout << iter->first << ":" << iter->second << ";";}cout << endl;}for(iter = id_name2.begin(); iter != id_name2.end(); iter++){cout << iter->first << ":" << iter->second << ";";}cout << endl;for(iter = id_name3.begin(); iter != id_name3.end(); iter++){cout << iter->first << ":" << iter->second << ";";}cout << endl << endl;//5.查找
#if 0// 关键字查询,找到则返回指向该关键字的迭代器,否则返回指向end的迭代器// 根据map的类型,返回的迭代器为 iterator 或者 const_iteratoriterator find (const key_type& k);const_iterator find (const key_type& k) const;
#endifint find_key = 28;  //改为1111什么的试一下if(id_name.end() == (iter = id_name.find(find_key))){cout << "not find out data with key = " << find_key << endl;}else{cout << "find success! " << endl << "-->key:" << iter->first << endl << "-->value:" << iter->second << endl; }cout << endl; //6.删除
#if 0// 删除迭代器指向位置的键值对,并返回一个指向下一元素的迭代器iterator erase( iterator pos )// 删除一定范围内的元素,并返回一个指向下一元素的迭代器iterator erase( const_iterator first, const_iterator last );// 根据Key来进行删除, 返回删除的元素数量,在map里结果非0即1size_t erase( const key_type& key );// 清空map,清空后的size为0void clear();
#endifint num_id_name = id_name.erase(28);for(iter = id_name.begin(); iter != id_name.end(); iter++){cout << iter->first << ":" << iter->second << ";";}cout << endl;return 0;
}

附录:摘录及参考资料

  1. 《c++ primer plus》
  2. C++中STL用法超详细总结
  3. C语言中文网
  4. [C++ STL] 各容器简单介绍

C++标准模板库(STL)(3) 之 vector map容器快速学习 (自学笔记)相关推荐

  1. 标准模板库 STL 使用之 —— vector 使用 tricks

    1. 从已有 vector(或数组)中复制 vector<int> a{....}; int an = a.size(); int half = an/2; vector<int&g ...

  2. C++ 标准模板库(STL)

    C++ 标准模板库(STL) C++ STL (Standard Template Library标准模板库) 是通用类模板和算法的集合,它提供给程序员一些标准的数据结构的实现如 queues(队列) ...

  3. c++标准模板库STL【快速查找】【最全】【常用】【语法】

    c++标准模板库STL[快速查找][最全][常用][语法] c标准模板库STL快速查找最全常用语法         vector- 变长数组         set-内部自动有序且不含重复元素     ...

  4. c语言stl模板,c/c++开发分享C++ 标准模板库 STL 顺序容器详解

    c++ 标准模板库 stl 顺序容器 容器 顺序性 重复性 支持迭代器 vector 动态数组 无序 可重复 随机访问迭代器 deque 双向队列 无序 可重复 随机访问迭代器 list 双向链表 无 ...

  5. 13 标准模板库STL【C++】

    13 标准模板库STL 13- 判断题 单选题 填空题 程序填空题 函数题 7-1 .查找电话号码 7-2 姓名排序 7-3 Score Processing 13+ 编程题 7-1 查找成绩并折算后 ...

  6. 第十章 标准模板库STL

    第十章 标准模板库STL 因为是在复习时重写的,无法在PTA上验证,编程题格式可能有误. 判断题 1.可以通过下标随机访问向量vector中的元素.(T) 2.当向量对象的内存用完之后,就会产生越界错 ...

  7. 标准模板库STL(Standard Template Library)

    标准模板库STL(Standard Template Library)指南 /*刘振飞liuzf@pku.org.cn 1999-10-20*/ / *版权所有 (C) 1999-2004 刘振飞li ...

  8. C++中标准模板库STL基本概念

    0. 前言 C++语言的一大优势就是便于软件的重用,而重用体现在两方面: 1. 面向对象思想:继承和多态,标准类库 2. 泛程序设计(Generic Programming)思想:模板机制,标准模板库 ...

  9. 蓝桥杯算法竞赛系列第0章——蓝桥必考点及标准模板库STL(上)(万字博文,建议抱走)

    欢迎来到:遇见蓝桥遇见你,不负代码不负卿! 目录 ​ 一.蓝桥必考点剖析 二.什么是STL 三.vector的常见用法详解 1.vector的定义 2.vector容器内元素的访问 (1).通过下标访 ...

  10. C++ ——模板 标准模板库STL

    C++ 知识基础 流操作符 类 & 基础 初始化和重载 类 & 高级 继承和多态 模板 & 标准模板库STL 目录 C++ 一.模板 1.函数模板 2.类模板 二.标准模板库S ...

最新文章

  1. uniapp同步获取用户信息_微信小程序云开发教程微信小程序的API入门获取用户身份信息系列API...
  2. 数字电路时钟问题——Jitter与Skew区别
  3. 592zn rom/apk 自动签名工具_ios超级签名服务器
  4. SDUT-SQL题解
  5. C# 断点续传原理与实现
  6. 「thunar」给thunar增加搜索文件功能
  7. [10秒学会] - iOS录制屏幕 ReplayKit
  8. 前端进阶之路-利用Jenkins快速打造前端项目自动化工作流
  9. unity3D汉化包Localization,我的软件是unity3D 2018.4.8c3亲测有效
  10. python使用cookie登陆新浪微博用户信息
  11. ubuntu软件商店提示has install-snap change in progress问题
  12. 透明质酸(玻尿酸)ELISA试剂盒解决方案
  13. 2021-05-11 MongoDB面试题 MongoDB是什么
  14. 那个牛逼的斯坦福大学
  15. 白盒测试——NextDate函数测试(基本路径覆盖法)
  16. 《逆袭进大厂》第十五弹之智力情景题 | 个人博客
  17. 代码精进之路-读后感
  18. [python] 正则“^[a-zA-Z]” 和 “[^a-zA-Z]”的区别
  19. [计算机网络] CSMA/CD 协议限定数据帧最小长度为 64B 不变,根据给定的数据传输速率计算得到争用期长度
  20. 魏晋南北朝:北国飘雪(一)

热门文章

  1. java 导出word_java导出生成word
  2. HitPaw Watermark Remover v1.2.0.3 图片视频水印去除
  3. android触摸 apk,超级触控(流畅触屏)apk
  4. 又一华尔街之狼?从洗碗工到公司董事长成功之路
  5. 理解手机中的感应器模块:重力感应/光线感应/电子罗盘/陀螺仪模块功能
  6. 学田岛电脑绣花制版新人上手教程之一
  7. 三星S5P6818 (ARM Cortex-A53架构)
  8. Excel不同列多条件计数
  9. win7怎么修改计算机皮肤,鼠标指针怎么换?小编教你win7系统更换鼠标指针皮肤的方法...
  10. java程序设计概念对象先行_Java程序设计概念:对象先行(原书第8版)简介,目录书摘...