【发布时间】:2011-03-24 07:26:53
【问题描述】:
std::list<std::pair> 和 std::map 有什么区别?列表也有find 方法吗?
【问题讨论】:
标签: c++ stl stdmap std-pair stdlist
std::list<std::pair> 和 std::map 有什么区别?列表也有find 方法吗?
【问题讨论】:
标签: c++ stl stdmap std-pair stdlist
std::map<X, Y>:
Xs)find() 方法 (O(log n)),通过 Key 查找 Key-Value 对map[key],速度也很快std::list<std::pair<X, Y> >:
Xs 和Ys 的简单序列。它们会按照您放入的顺序保留。list 中查找特定键是O(N)(无特殊方法)splice 方法。【讨论】:
std::pairstd::pair 是一个模板化的元组结构,限制为 2 项,称为 first 和 second:
std::pair<int, std::string> myPair ;
myPair.first = 42 ;
myPair.second = "Hello World" ;
std::pair 被 STL(和其他代码)用作“通用容器”来同时聚合两个值,而无需重新定义另一个 struct。
std::mapstd::map 是一个模板关联容器,将键和值关联在一起。最简单(但不是更有效)的例子是:
std::map<int, std::string> myMap ;
myMap[42] = "Fourty Two" ;
myMap[111] = "Hello World" ;
// ...
std::string strText ; // strText is ""
strText = myMap[111] ; // strText is now "Hello World"
strText = myMap[42] ; // strText is now "Fourty Two"
strText = myMap[23] ; // strText is now "" (and myMap has
// a new value "" for key 23)
std::pair 和 std::map
注意:这是原始问题的答案,未经编辑。
std::map 函数需要同时将迭代器返回到键和值以保持效率......所以显而易见的解决方案是将迭代器返回到对:
std::map<int, std::string> myMap ;
myMap[42] = "Fourty Two" ;
myMap[111] = "Hello World" ;
myMap.insert(std::make_pair(23, "Bye")) ;
std::map<int, std::string>::iterator it = myMap.find(42) ;
std::pair<int, std::string> keyvalue = *it ; // We assume 42 does
// exist in the map
int key = keyvalue.first ;
int value = keyvalue.second ;
std::list<std::pair<A,B> > 和 std::map<A,B>
注意:问题编辑后编辑。
因此,乍一看,配对地图和配对列表看起来是一样的。但事实并非如此:
地图本质上是由提供的函子排序的,而列表将 [A,B] 对保留在您放置它们的位置。这使得 map 的插入 O(log n),而列表中的原始插入是一个恒定的复杂性(搜索插入它的位置是另一个问题)。
您可以使用一对列表在一定程度上模拟地图的行为,但请注意,地图通常实现为项目树,而列表是项目的链式列表。因此,像二分法这样的算法在地图中的运行速度要比在列表中快得多。
因此,在地图中找到一个项目是 O(log n),而在无序列表中是 O(n)。如果列表是有序的,并且您想使用二分法,您将不会获得预期的性能提升,因为遍历项目列表无论如何都是逐项完成的。
(在我一年前工作的一个项目中,我们用一组相同的有序项目替换了一个有序项目列表,它提高了性能。该集合具有与地图相同的内部树结构,我想同样的提升也适用于此)
【讨论】:
std:pair 恰好包含两个对象。 std:map 持有成对对象的集合。
你不能在pair上使用find(),因为没有什么可找到的。您想要的对象是pair.First 或pair.Second
更新:
假设您的意思是 map<> 和 list<pair<> > 之间的区别:应该实现映射以快速查找 key 成员。 list 只有一个简单的线性列表。在列表中查找一个项目需要遍历整个列表。但是,std::find() 对两者都有效。
【讨论】:
(澄清后编辑)
std::map 针对快速搜索进行了优化。它有自己的find 方法,该方法使用其内部结构来提供良好的性能。一般来说,它只会检查log(N)键,其中N是映射中的项目数。
std::list<std::pair> 是一个简单的链表,所以只支持逐个元素的遍历。您可以使用单独的std::find 算法,或带有自定义谓词的std::find_if,只检查first 成员以更好地匹配std::map::find 的语义,但这会很慢。事实上,它必须查看列表中的每一对对以查找任何失败的搜索,并且对于任何成功的搜索,平均将查看一半。
【讨论】:
STL 映射是关联数组,通常在内部实现为哈希映射。如果你想迭代一个 STL 映射,它将返回一个 STL 对。
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<string, int> myMap;
myMap["myKey"] = 1337;
map<string, int>::iterator myIterator = myMap.begin();
pair<string, int> myPair = *myIterator;
cout<<"the key \""<<myPair.first<<"\" maps to the value of "<<myPair.second<<endl;
cout<<"the key \"myKey"\" maps to the value of "<<myMap["myKey"]<<endl;
return 0;
}
我建议您在谷歌上搜索并阅读完整的 STL API 参考,因为 STL(除了将布尔值存储在向量中和其他类似的怪事之外)实现了许多您希望在任何程序中使用而无需重新发明的数据结构功能轮子。
【讨论】:
maps 不是由哈希图实现的,而是由红黑(或类似)树实现的。
Map可以在O(log n)的范围内提供更好的搜索时间, wilw list 的查找时间可以为 O(n)。
【讨论】:
std::pair 仅用于将 2 个对象组合在一起(例如,“页面上的坐标”由 X 和 Y 组成)。
std::map 是从一组对象到另一组对象的映射。
尝试在一对上使用 find 方法是没有意义的,因为在你知道顺序的两个事物的列表中查找某些东西有什么意义,即使该 find 方法存在于它的 pair 类中没有。
但是,如果您愿意,可以使用 std::pair 作为映射值。
【讨论】: