c++/STL/map中怎样获取map中第i个元素

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++/STL/map中怎样获取map中第i个元素相关的知识,希望对你有一定的参考价值。

Map的iterator貌似不可以直接加减
除了线性遍历以外没有别的方法吗?线性遍历一定会TLE

比如
map<int,int> m;
m[3]=2;m[6]=7;m[9]=3;m[100]=9;

想要m的第3个元素,返回上述中的3;

另外,得到某个迭代器,那么怎么知道它是第几个元素?
比如同上述里,通过first=100返回4

1、在对应的javascript文件中,定义一个Map数据结构变量m,并分别打印值和类型,如下图所示。

2、保存代码并运行,结果发现Map 以及对象类型(Map是一种对象),如下图所示。

3、接着调用Map数据结构中的set方法,添加5个元素,其中有一个的key值重复了,如下图所示。

4、保存代码并运行,查看控制台打印结果,发现key-value值,如下图所示。

5、使用get()方法获取单个元素,传入的参数是key值。

6、最后保存代码并运行,可以查看到Map数据结构中的value值。

参考技术A map将key和value组成的pair作为元素,根据key的排序准则自动将元素排序,map中的存取封装了二叉树,因此map按照自己的算法来进行存取,跟你给元素赋值的顺序无关,无论哪一个先赋值最终的map中数据排列属性都是:m[3]=2;m[6]=7;m[9]=3;m[100]=9; 即按照key的大小进行了排序。m[3]=2;m[6]=7;m[9]=3;m[100]=9情况你说的第三个是m[9]=3,如果m[9]=3;m[100]=9;m[3]=2;m[6]=7;你所谓的第三个元素是不是就是:m[3]=2? 这种情况插入到map后map第三个数据依然是m[3]=3.
map就是为了按照key来进行key-value的查看,可以考虑使用list 将键值对做到一个list中,list是顺序存取的,你取的顺序根据有的存顺序决定。本回答被提问者和网友采纳
参考技术B #include<map>
#include<string>
#include<iostream>

int main()

map<string,int> words;
map<string,int>::iterator it=words.begin();
for(;it!=words.end();++it)
cout<<"key:"<<it->first
<<"value:"<<it->second<<end1;
return 0;
Top
参考技术C map内部是用红黑树实现的,既然是树,怎么说是“第3个元素”呢?

STL的map容器将第3个模板参数设为less_equal或greater_equal会怎样?

最近都在学Linux系统编程,用C就足矣,有段时间没碰C++了,于是实现些算法练手。

实现多项式乘法的时候发现有几项没有合并同类项,最终调试到这一步时发现了问题。

技术分享

res是map类型,用find查找key为1991的key-value时,结果得到的却是<12,1>的key-value。

于是转去看那段代码,发现了问题。因为map默认是升序排列,我最后需要打印的多项式是按照幂次数(即这里res的key)降序排列,所以我需要设置map的第3个模板参数,但是由于代码补全我没确认就选择了。

map<int, int, std::greater_equal<int>> res;

我的本意是用std::greater<int>,结果补全的时候没仔细看,补全成了greater_equal<int>,也就是大于或等于。

C++的map的常见实现是内部维护了一颗红黑树(二叉平衡树)从而得到按照key的大小排列的key-value,因为二叉平衡树默认是左子节点<父节点<右子节点,而怎么比较节点之间的大小则是个问题,因为节点可以是类而不是基本数据类型(int、double等等),于是就有了map第3个模板参数,默认是less<>,也就是对基本数据类型来说是,而对类(设为Object)来说则是它的bool operator < (const Object&) const方法。

所以关键是对象之间的operator < 的定义。类似地,在进行find()等需要查找的操作时,取决于对象之间的operator == 的定义

gdb跟踪find()函数的运行过程到达关键代码

2288      template<typename _Key, typename _Val, typename _KeyOfValue,
2289               typename _Compare, typename _Alloc>
2290        typename _Rb_tree<_Key, _Val, _KeyOfValue,
2291                  _Compare, _Alloc>::iterator
2292        _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
2293        find(const _Key& __k)
2294        {
2295          iterator __j = _M_lower_bound(_M_begin(), _M_end(), __k);
2296          return (__j == end()
(gdb) 
2297              || _M_impl._M_key_compare(__k,
2298                        _S_key(__j._M_node))) ? end() : __j;
2299        }

含义很好理解,通过_M_lower_bound函数返回迭代器__j,然后若__j为end()或者对__k(插入节点)和__j(下界节点)的节点值的比较为真,则返回end(),否则返回__j。_M_key_compare即我们传入map的第三个模板参数,后面记为operator < (),对int默认定义是:less<int>,即符合以下规则

operator < (1,2):真;operator < (1,1):假;operator < (1,0):假。

_M_lower_bound可以参照STL算法lower_bound的定义(http://www.cplusplus.com/reference/algorithm/lower_bound/)

Returns an iterator pointing to the first element in the range [first,last) which does not compare less than val.

返回按照operator<()排好的升序数组中第1个不小于val的数,也就是第1个operator < (数组元素,待查找值)为假的数,示例如下:

【case 1】数组:1 2 4 5;查找:3。   1<3:真;2<3:真;4<3:假。 ——返回4,对应:查找失败

【case 2】数组:1 2 3 5;查找:3。   1<3:真;2<3:真;3<3:假。 ——返回3,对应:查找成功

回顾刚才的代码,我们可以看到_M_impl._M_key_compare(__k, _S_key(__j._M_node))的意义在哪

operator < (查找值,lower_bound的返回值)为真对应的是上面的case 1,也就是查找失败,find()查找失败会返回end()

 

回到map上来,也就是说,map调用find()方法不需要operator==的定义,只需要operator<的定义即可。

那么假如operator<被定义为less_equal而不是less呢?

case 1不变,我们重新考虑上面的case 2:1<3:真;2<3:真;3<3:真;5<3:假,返回5。

——等等,3<3为什么为真?注意,此时的<已经不是数学意义上的小于(<)了,而是调用了operator<(),operator<()被赋予数学意义上的小于或等于(<=)的意义,那么3<3的结果就等同于数学意义上的3<=3。

也就是说,模板参数设为less_equal时,lower_bound永远不会返回和查找值一样的值,也就是说,find()函数永远不会返回end(),即查找失败。

(greater_equal和less_equal类似,只不过升序改成降序)

最后给个测试程序来证明我的结论

#include <iostream>
#include <map>
#include <functional>
using namespace std;

int main()
{
    map<int, int, greater_equal<int>> m;
    int key = 250;
    m.emplace(key, 0);

    for (int val = 100; val < 120; val++)
    {
        // 若m中不存在key则将<key,val>添加进去
        if (m.find(key) == m.end())
            m.emplace(key, val);
    }

    // 显示map的数据
    for (auto& x : m)
        cout << x.first << "=>" << x.second << endl;

    return 0;
}
$ g++ test.cpp -std=c++11
$ ./a.out 
250=>119
250=>118
250=>117
250=>116
250=>115
250=>114
250=>113
250=>112
250=>111
250=>110
250=>109
250=>108
250=>107
250=>106
250=>105
250=>104
250=>103
250=>102
250=>101
250=>100
250=>0

map中一个key对应尽可能多个value,这就是使用less_equal或greater_equal作为map第3个模板参数的下场了

以上是关于c++/STL/map中怎样获取map中第i个元素的主要内容,如果未能解决你的问题,请参考以下文章

c++11中,为啥可以用const_iterator删除map/multimap中的元素

如何利用C++/STL vector的sort算法对元素是自定义类型进行排序

c++ stl unordered_map 如何打印其所有值?

怎么在jsp页面获取每个Map中key所对应的value值得 size啊

[C++STL]map容器用法介绍

HashSet set=map.entrySet();//将map类型数据转换成集合set类型的。