vimer linux kernel 爱好者

c++中 map set的用法

2019-06-17

map的用法

其实,如果是做算法题目的话,c++是一定需要掌握的语言(对于纯c来讲,也许真正的c大师完全可以纯手撸出来)。现在,自己简单记录下c++中基本的数据结构的用法,今天重点回忆map。

map的基本概念不用解释,就是简单的”key”,”value”嘛,主要看操作。

声明

  map<int, int> m; // 声明存储两个整型的key value
  map<string, int> m;// decliam a map with string key typo and value int typo

遍历

我认为每一个数据结构都有自己的遍历方式,这是必须掌握的一种机制。使用c++的遍历呢,我们不能忘记iterator

 map<string, int> m;
   m["yubo"] = 1;
   m["hechun"] = 2;
   map<string, int>::iterator iter = m.begin();
   while(iter != m.end()){
    cout<< iter->first << ":" << iter->second <<endl;
    iter++;
   }
   /* 还可以使用for
   map<string, int>::iterator iter = m.begin();
   for(; iter != m.end(); iter++)
    cout<< iter->first<< ":"<<iter->second<<endl;
   */

使用for需要注意的地方就是,判断条件不能使用”<”(在迭代中)

begin(), end() 默认以key排序

哈哈,非常有意思!起初我还以为map是类似栈式的管理,看来真实贻笑大方了。目前来说,map这个数据结构可以按照key的值自动排序。当然,这个排序你可以使用,也可以不使用;既可以这样排序,也可以那样排序!有意思啊

另外注意的就是,end()指针没有指向元素,如果,特定需要end()的元素,需要提前减1.

 map<string, int> m;
   m["yubo"] = 1;
   m["hechun"] = 2;
   map<string, int>::iterator _start, _end;
   _start = m.begin();
   _end = m.end();
    _end--;
    cout << _start->first<<endl;
   cout << _end->first << endl;

结果先输出”hechun”,再输出”yubo”

擦除

以上面代码为例的话,就是删除遍历指针

m.erase(_start)

查找元素

map<string,int>::iterator itr=m.find(val); //Gives the iterator to the element val if it is found otherwise returns m.end() .
Ex: map<string,int>::iterator itr=m.find("Maps"); //If Maps is not present as the key value then itr==m.end()."")

更新元素

还是使用遍历指针:

访问元素

To get the value stored of the key “MAPS” we can do m[“MAPS”] or we can get the iterator using the find function and then by itr->second we can access the value.

插入键值对

使用 `std::pair<string, int>(),还可以参观这个 article

综合练习

首先输入一个数字,代表后面有几个输入行:

7
1 Jesse 20
1 Jess 12
1 Jess 18
3 Jess
3 Jesse
2 Jess
3 Jess

其中,’1’代表插入姓名和成绩,当然有多个相同,需要自己更新的。’2’代表删除该学生的信息,’3’代表查询该学生的成绩。 Solution:

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <set>
#include <map>
#include <algorithm>
using namespace std;
int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
    map<std::string, int> m;
    int n, type;
    cin >> n ; // nums of query
    for(int i = 0; i < n;i++){
            string name;
            int marks;
            cin >> type;   // the first type on per line
            if (type == 1){
	                cin >> name >> marks;  // how to iter and update value
	                map<string,int>::iterator iter = m.find(name);
	                if(iter == m.end())
	                    m.insert(std::pair<string, int>(name, marks));
	                    // maybe use
	                else
	                    iter->second += marks; // update value
	            }
            else if (type == 2){
	                cin >> name;
	                m.erase(name);
	            } else {
		                cin >> name;
		                cout << m[name] << endl; //
		            }
        }
    return 0;
}

其中,插入元素那里值得注意,上面的方法使用m.insert(std::pair<string, int>(name, marks)), 还可以使用make_pair()的方法, 注意,这里没有 <>.

unordered_map

前面介绍的map是一个唯一键的有序序列,而在unordered_map中键可以以任何顺序存储,所以是无序的。Map是作为平衡的树结构实现的,这就是为什么可以维护元素之间的顺序(通过特定的树遍历)。map操作的时间复杂度为O(Log n),而对于unordered_map,平均为O(1)。

以下代码如同map的代码一样,没有什么特别的地方。

#include <unordered_map>
#include <iostream>
using namespace std;

int main() {
        unordered_map<string, int> umap;

        // insert values by using "[]" operator
        // 当然 还可以使用make::pair的形式插入进去  umap.insert(make_pair("e", 2.718));
        umap["vimer"] = 10;
        umap["test"] = 11;
        umap["lele"] = 12;

        for(const auto &entry : umap){  // 使用引用的方式 省去copy的开销
                cout << entry.first <<" " <<entry.second << endl;
        }
}

如果value值为其他容易,在插入新值之前,需要先做初始化。如下:

using namespace std;

int main() {

        unordered_map<string, vector<int>> keys;
        keys["a"] = vector<int>(); // Initialize key with all null vector
        keys["a"].push_back(1);
        keys["a"].push_back(2);

        for (const int &x : keys["a"]){
                cout << x << endl;
        }
}

或者其他类似的:

drawQueue.insert(std::make_pair(type, std::vector<Object*>()));
// If using C++11, the previous statement can be simplified to:
drawQueue.emplace(type, std::vector<Object*>());

参考这里

下面介绍几个API。

count

这个方法可以看成测试某一个keys是否存在map容器中, 如下:

#include <iostream>
#include <string>
#include <unordered_map>

int main ()
{
  std::unordered_map<std::string,double> mymap = {
     {"Burger",2.99},
     {"Fries",1.99},
     {"Soda",1.50} };

  for (auto& x: {"Burger","Pizza","Salad","Soda"}) {
    if (mymap.count(x)>0)
      std::cout << "mymap has " << x << std::endl;
    else
      std::cout << "mymap has no " << x << std::endl;
  }

  return 0;

上面的代码摘自c++.com c++实在是太变态了。


Comments

Content