c++ std::map

  • 重点总结:
  • map 是STL的一个关联容器。里面的数据都是成对出现的,第一个是关键字(key),每个关键字只能在map中出现一次。第二个是该关键字的值(value)
  • map底层实现是红黑树,这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的。
  • map的插入、删除操作复杂度为O(logN),查找的复杂度基本为O(logN)。

  • 常用函数
  • 1. 函数构造、随机访问
    • 1.1 构造函数
    • 1.2 operator[]、at() 功能介绍
  • 2. 插入函数
    • 2.1 insert()
    • 2.2 emplace()
    • 2.3 emplace_hint()
  • 3. 删除-erase()
  • 4. 查找 find()、count()、*_bound()
    • 4.1 find()、count()
    • 4.2 lower_bound()、upper_bound()
  • 5. 遍历map


常用函数

  • 以下函数顺序与www.cplusplus中相同。

    at					返回key对应value的引用
    begin	         	返回指向map头部的迭代器
    cbegin				返回指向容器头的迭代器-const
    cend				返回指向容器尾元素后一个位置的迭代器 - const
    clear        		删除所有元素,size=0
    count        		返回对应key出现的次数,0或1
    crbegin				返回指向容器最后一个元素的 逆序 迭代器 - const
    crend				返回指向容器头元素前一个位置的 逆序 迭代器 - const
    
    emplace				当容器中未包含参数key时,插入元素 move
    emplace_hint		使用迭代器作为插入标示,当容器中无该key时,才会将其插入在标示位前
    empty	         	如果map为空则返回true
    end		           	返回指向map末尾的迭代器
    equal_range		   	返回一个pair,包含两个迭代器,first是lower_bound(),second是upper_bound()
    erase	         	删除元素
    find	          	查找元素,找到返回迭代器,未找到返回map.end()
    get_allocator
    insert	        	插入元素
    key_comp
    lower_bound			返回一个迭代器,该迭代器指向>=给定key的 第一个位置
    
    max_size	      	返回可以容纳的最大元素个数
    operator=
    operator[]			若key存在容器中,返回对应value的引用。否则,插入具有该key的新元素,并返回value的引用
    rbegin				返回指向容器最后一个元素的 逆序 迭代器
    rend				返回指向容器头元素前一个位置的 逆序 迭代器
    size          		返回map中元素的个数
    swap
    upper_bound    		返回一个迭代器,该迭代器指向>给定key的 第一个位置
    value_comp
    

1. 函数构造、随机访问

  • 头文件#include

1.1 构造函数

// key,value均可为自定义的对象或其他类型
// 当key自定义的对象时,需实现比较大小功能
explicit map(const key_compare& comp = key_compare(),
             const allocator_type& alloc = allocator_type());
explicit map(const allocator_type& alloc);			// [1]. 默认构造

template <class InputIterator>
  map(InputIterator first, InputIterator last,		// [2]. range
      const key_compare& comp = key_compare(),
      const allocator_type& = allocator_type());

map(const map& x);									// [3]. copy
map(const map& x, const allocator_type& alloc);

map(map&& x);										// [4]. move
map(map&& x, const allocator_type& alloc);

map(initializer_list<value_type> il,				// [3]. initializer list
    const key_compare& comp = key_compare(),
    const allocator_type& alloc = allocator_type());

测试代码:

int main () {
    std::map<char,int> first;                               // [1]. 默认构造
    first['a']=10;
    first['b']=30;
    first['c']=50;
    first['d']=70;

    std::map<char,int> second(first.begin(),first.end());   // [2]. range

    std::map<char,int> third(second);                       // [3]. copy

    std::map<char,int,classcomp> fourth;                    // 使用自定义结构class

    bool(*fn_pt)(char,char) = fncomp;
    std::map<char,int,bool(*)(char,char)> fifth(fn_pt);     // 使用函数指针进行 compare

    return 0;
}

1.2 operator[]、at() 功能介绍

  • 两函数相同点:
      当key存在于容器中时,两函数均返回key对应value的引用。
  • 两函数区别:
      I. operator[],当参数key不存在时,构造.firstkeypair插入到容器中,.second(即val)为默认值(或默认构造的对象),并返回对应value的引用。
      II. at(),如果该key不存在则抛出异常。

重点:使用operator[],即使不对其返回的引用进行操作,也会创建了一个新的元素,容器size+1。例题代码如下:

int main() {
    std::map<std::string,int> mymap = { { "alpha", 0 },
                                        { "beta",  0 } };

    mymap.at("alpha") = 10;			// at()
    mymap.at("beta") = 20;
    mymap["gamma"] = 30;			// 1. add element: pair("gamma", 30)
    mymap["Haha"];                  // 2. add new element, second值为int 默认值0
    mymap["Hehe"]++;                // 3. add new element, second值为int 默认值0+1  ******************

    for (auto& x: mymap) {
        std::cout << x.first << ": " << x.second << '\n';
    }

    return 0;
}
  • 输出结果:

Haha: 0
Hehe: 1
alpha: 10
beta: 20
gamma: 30


2. 插入函数

2.1 insert()

  • operator[]insert()emplace()均可以实现元素插入。
  • 重点: 由于容器中元素的key是唯一的,因此插入操作将检查容器中是否已存在与插入元素的key相同的key,如果已存在,则不插入该元素,并返回该key对应的迭代器。

insert() 函数原型如下:

// [1]. single element 单个元素插入,返回插入位置iterator 和标示位
//		在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个key时,插入失败,标示位为false
pair<iterator,bool> insert(const value_type& val);					
template <class P> pair<iterator,bool> insert(P&& val);

// [2]. 通过迭代器位置插入单个元素,返回插入位置的iterator
iterator insert(const_iterator position, const value_type& val);
template <class P> iterator insert(const_iterator position, P&& val);

// [3]. 将迭代器范围[first terator, last terator)内的元素插入当前容器中
template <class InputIterator>
  void insert(InputIterator first, InputIterator last);

// [4].initializer list,将list中元素插入
void insert(initializer_list<value_type> il);
int main() {
	std::map<char,int> mymap;

    // [1]
    mymap.insert( std::pair<char,int>('a',100) ); 			// [1]. 单个元素插入
    mymap.insert( std::pair<char,int>('z',200) );

    std::pair<std::map<char,int>::iterator,bool> ret;
    ret = mymap.insert( std::pair<char,int>('z',500) );		// [1]. 返回值
    if (ret.second==false) {
        std::cout << "[1] element 'z' already existed";
        std::cout << " with a value of " << ret.first->second << '\n';
    }
	
    std::map<char, int>::iterator it = mymap.begin();
    mymap.insert(it, std::pair<char, int>('b', 300));  		// [2]. 效率最高
    mymap.insert(it, std::pair<char, int>('c', 400));

    
  	std::cout << "mymap:\n";
    for (it=mymap.begin(); it!=mymap.end(); ++it)
        std::cout << "[2] " << it->first << " => " << it->second << '\n';


    std::map<char, int> anothermap;							// [3]. range
    anothermap.insert(mymap.begin(), mymap.find('c'));

    std::cout << "anothermap:\n";
    for (it=anothermap.begin(); it!=anothermap.end(); ++it)
        std::cout << "[3] " << it->first << " => " << it->second << '\n';


    std::map<char, int> four_map;							// [4]. initializer list
    four_map.insert({ { 'd', 100 }, {'e', 200} });

    std::cout << "four_map:\n";
    for (it=four_map.begin(); it!=four_map.end(); ++it)
        std::cout << "[4] " << it->first << " => " << it->second << '\n';
    
    return 0; 
}

[1] element ‘z’ already existed with a value of 200
mymap:
[2] a => 100
[2] b => 300
[2] c => 400
[2] z => 200
anothermap:
[3] a => 100
[3] b => 300
four_map:
[4] d => 100
[4] e => 200

2.2 emplace()

  • emplace() 函数原型如下:
std::map::emplace
template <class... Args>
	pair<iterator,bool> emplace (Args&&... args);

    emplace()可避免复制和移动操作,在该文中有详细介绍:c++ 右值引用、移动语义、std::move、完美转发std::forward、emplace。

    值得注意的是,只有当Map中现有元素的键与这个元素的键不同时,才会构造这个元素。否则不会构造,下面是一个示例:

int main() {
    std::map<char,int> mymap;

    mymap.emplace('x',100);
    mymap.emplace('y',200);
    mymap.emplace('z',100);
    
    auto ans = mymap.emplace('z',888888);  // 无效
    std::cout << ans.second << endl;

    std::cout << "mymap contains:";
    for (auto& x: mymap)
        std::cout << " [" << x.first << ':' << x.second << ']';
    std::cout << '\n';
    
    return 0; 
}

0
mymap contains: [x:100] [y:200] [z:100]

2.3 emplace_hint()

  • <2>. emplace_hint() 函数原型:
std::map::emplace_hint
template <class... Args>
  iterator emplace_hint(const_iterator position, Args&&... args);
  • emplace_hint() 使用一个迭代器作为插入标示位,只有当Map中现有元素的键与这个元素的键不同时,才会构造这个元素。新元素会插入在标示位前。
int main () {
	std::map<char,int> mymap;
	auto it = mymap.end();
	
	it = mymap.emplace_hint(it,'b',10);			// end()前插入
	mymap.emplace_hint(it,'a',12);				// 'b' 前插入
	mymap.emplace_hint(mymap.end(),'c',14);
	mymap.emplace_hint(mymap.end(),'c',15);       // 插入失败
	
	std::cout << "mymap contains:";
	for (auto& x: mymap)
		std::cout << " [" << x.first << ':' << x.second << ']';
	std::cout << '\n';
	
	return 0;
}

mymap contains: [a:12] [b:10] [c:14]


3. 删除-erase()

C++11中,erase() 有以下几种类型:

// [1] 删除迭代器指向位置的元素,并返回一个指向下一元素的迭代器
iterator erase(const_iterator position);	

// [2] 根据key来进行删除, 返回删除元素的数量(0或1)
size_type erase(const key_type& k);			

// [3] 删除[first, last)范围内元素,返回指向下一元素的迭代器
iterator erase(const_iterator first, const_iterator last);									

测试代码

#include 
#include 

int main () {
	std::map<char,int> mymap;
	std::map<char,int>::iterator it;
	
	// insert some values:
	mymap['a']=10;
	mymap['b']=20;
	mymap['c']=30;
	mymap['d']=40;
	mymap['e']=50;
	mymap['f']=60;
	
	it=mymap.find('b');
	mymap.erase(it);                   	// 方法[1] erasing by iterator
	
	mymap.erase('c');                  	// 方法[2] erasing by key
	
	it=mymap.find('e');
	mymap.erase(it, mymap.end()); 		// 方法[3] erasing by range
	
	// show content:
	for (it=mymap.begin(); it!=mymap.end(); ++it)
	  std::cout << it->first << " => " << it->second << '\n';
	
	return 0;
}
  • 输出结果

a => 10
d => 40


4. 查找 find()、count()、*_bound()

4.1 find()、count()

  • [1]. find()函数通过key查找对应键值对
        - 若key存在于容器中,返回key对应键值对的iterator
        - 否则返回map.end()
int main() {
    std::map<char,int> mymap;
    std::map<char,int>::iterator it;

    mymap['a']=50;
    mymap['b']=100;
    mymap['c']=150;

    it = mymap.find('b');
    if (it != mymap.end())
        mymap.erase(it);       // 若找到key='b', 则删除对应元素

    // print content:
    std::cout << "elements in mymap:" << '\n';
    std::cout << "a => " << mymap.find('a')->second << '\n';
    std::cout << "c => " << mymap.find('c')->second << '\n';

    return 0;
}
  • 输出结果

elements in mymap:
a => 50
c => 150

  • [2]. count()返回key出现的次数
int main() {
    std::map<char,int> mymap;
    char c;

    mymap ['a']=101;
    mymap ['c']=202;
    mymap ['f']=303;

    for (c='a'; c<'h'; c++) {
        std::cout << c << ", ";

        if (mymap.count(c)>0)
            std::cout << " is an element of mymap.\n";
        else 
            std::cout << " no.\n";
    }

    return 0;
}
  • 打印结果

a, is an element of mymap.
b, no.
c, is an element of mymap.
d, no.
e, no.
f, is an element of mymap.
g, no.

4.2 lower_bound()、upper_bound()

  • lower_bound() 返回一个迭代器,该迭代器指向>=给定key的 第一个位置。函数原型:
// std::map::lower_bound
iterator lower_bound (const key_type& k);
const_iterator lower_bound (const key_type& k) const;
  • upper_bound() 返回一个迭代器,该迭代器指向>给定key的 第一个位置。函数原型:
// std::map::upper_bound
iterator upper_bound (const key_type& k);
const_iterator upper_bound (const key_type& k) const;

    例:

int main () {
	std::map<char,int> mymap;
	std::map<char,int>::iterator itlow,itup;
	
	mymap['a']=20;
	mymap['b']=40;
	mymap['c']=60;
	mymap['d']=80;
	mymap['e']=100;
	
	itlow=mymap.lower_bound ('b');  // >='b', 此处返回迭代器指向key为'b'的元素
	itup=mymap.upper_bound ('d');   // >'d',  此处返回迭代器指向key为'e'的元素
	
	mymap.erase(itlow,itup);        // erases [b,e)
	
	// print content:
	for (std::map<char,int>::iterator it=mymap.begin(); it!=mymap.end(); ++it)
		std::cout << it->first << " => " << it->second << '\n';
	
	return 0;
}

a => 20
e => 100


5. 遍历map

  • 迭代器遍历
int main () {
	std::map<char,int> mymap;
	std::map<char,int>::iterator it;
	
	// insert some values:
	mymap['a']=10;
	mymap['c']=30;
	mymap['b']=20;
	mymap['d']=40;
	mymap['e']=50;
	mymap['f']=60;
	
	// show content:
	for (it=mymap.begin(); it!=mymap.end(); ++it)
		std::cout << it->first << " => " << it->second << '\n';
	
	return 0;
}

map容器中元素是有序的,所以打印也是有序的:
a => 10
b => 20
c => 30
d => 40
e => 50
f => 60

你可能感兴趣的:(C++,STL)