C++ 已知整数值的快速优雅单向映射
我必须把一组已知的整数映射到另一组已知的整数,1对1的关系,所有这些都是预定义的,等等。所以,假设我有这样的东西(c++,简化,但你会明白的): 现在给定一个输入整数,比如79,我需要从地图中找到相应的结果(显然是12958)。有什么好的和快速的方法来做这件事,而不是你的循环运行?其他数据结构建议也很受欢迎,但是地图应该很容易手工在源代码中编写C++ 已知整数值的快速优雅单向映射,c++,C++,我必须把一组已知的整数映射到另一组已知的整数,1对1的关系,所有这些都是预定义的,等等。所以,假设我有这样的东西(c++,简化,但你会明白的): 现在给定一个输入整数,比如79,我需要从地图中找到相应的结果(显然是12958)。有什么好的和快速的方法来做这件事,而不是你的循环运行?其他数据结构建议也很受欢迎,但是地图应该很容易手工在源代码中编写 两组中的值都在0到2^16的范围内,只有大约130对。我想要的是一种非常简单的静态初始化数据的方法。为什么不使用哈希映射?它会给你多少恒定的检索时间来检
两组中的值都在0到2^16的范围内,只有大约130对。我想要的是一种非常简单的静态初始化数据的方法。为什么不使用哈希映射?它会给你多少恒定的检索时间来检索任何键。
std::map theMap;
std::map<int, int> theMap;
theMap[2] = 5;
std::map<int, int>::const_iterator iter = theMap.find(2);
if (iter != theMap.end())
iter->second; // found it
theMap[2]=5;
std::map::const_迭代器iter=theMap.find(2);
如果(iter!=theMap.end())
iter->second;//找到了
插入整数对,按键检索值,对数复杂度。如果您有一个非常大的数据集并且需要更快的检索,请使用std::tr1::无序映射或boost::无序映射(以防您的标准库没有tr1实现)。或者可能是最干净的。不幸的是C++没有内置的关联数组。
std::map<int,int> mymap; // the same with unordered map
// one way of inserting
mymap.insert ( std::make_pair(2,5) );
mymap.insert ( std::make_pair(79,12958) );
// another
mymap[2] = 5;
mymap[79] = 12958;
std::map mymap;//无序地图也是如此
//一种插入方式
mymap.insert(std::make_pair(2,5));
mymap.insert(std::make_pair(7912958));
//另一个
mymap[2]=5;
mymap[79]=12958;
查证
std::map<int,int>::const_iterator iter = mymap.find(2);
if ( iter != mymap.end() )
{
// found
int value = iter->second;
}
std::map::const_迭代器iter=mymap.find(2);
if(iter!=mymap.end())
{
//发现
int值=国际热核实验堆->秒;
}
unordered\u map
具有O(1)
摊销查找时间的优势,而不是O(logn)
的map
你的想法是对的,它是一个map。使用。使用地图
#include <map>
#include <iostream>
int main() {
std::map <int, int> m;
m[79] = 12958;
std::cout << m[79] << std::endl;
}
#包括
#包括
int main(){
std::map m;
m[79]=12958;
std::cout按键对数组进行排序并进行二进制搜索。如果您100%确定map
不会增加到1000个条目(配置文件!),则进行二进制搜索可能会更快
如果a
的值有一个合理的界限(例如低于1000),您可以使用a
作为保证O(1)复杂度的索引来创建一个简单数组。如果您使用gcc,您可以使用以下语法():
(遗憾的是,g++不支持这一点)
在任何其他情况下,请使用其他答案中所示的std::unordered_map
。如果源整数i
的数量相对较高(因此直接搜索效率较低),但仍然可以管理,则可以相对轻松地为输入整数构建完美的哈希函数hash(i)
(例如,使用)然后使用哈希值作为输出表map
output = map[hash(i)];
当然,如果输入值的范围相对较小,可以使用identity函数代替散列
,只需将整个过程转换为straghforward重新映射
output = map[i];
(如果是这样的话,你甚至可能都不会问。)你的伪代码几乎是有效的C++0x代码-但是C++0x需要的更少
map<int, int> theMap = { {2, 5}, {79, 12958 } };
assert ( theMap[ 2 ] == 5 );
map theMap={{2,5},{7912958};
断言(theMap[2]==5);
在“正常”C++中,你必须像这样初始化地图,仍然很优雅:
pair< int, int > map_array[2] = { make_pair(2, 5), make_pair(79, 12958) };
map< int, int > theMap( &map_array[0], &map_array[2] ); // sorts the array
assert ( theMap[ 2 ] == 5 );
pairmap_数组[2]={make_-pair(2,5),make_-pair(7912958)};
maptheMap(&map_数组[0],&map_数组[2])//对数组排序
断言(theMap[2]==5);
这是快速写入和快速运行
编辑:只是不要将映射设置为全局变量。(尽管这在C++0x中是安全的。)如果这样做,则只有在编译器选择在映射数组之后对其进行初始化时,它才会正确初始化,这是很难保证的。如果要成为全局变量,请使用theMap.assign(&map\u数组[0],&map\u数组[2])对其进行初始化;
跳转表。如果您能够使用它,开关可能会设置它,否则您可能需要一些程序集,但这可能是最快的方法。如果您需要编译时映射,可以使用以下模板:
// template to specialize
template<int T> struct int2int {};
// macro for simplifying declaration of specializations
#define I2I_DEF(x, v) template<> struct int2int<x> { static const int value = v; };
// definitions
I2I_DEF(2, 5) I2I_DEF(79, 12958) I2I_DEF(55, 100) // etc.
// use
#include <iostream>
int main()
{
std::cout << int2int<2>::value << " " << int2int<79>::value << std::endl;
return 0;
}
//要专门化的模板
模板结构int2int{};
//用于简化专门化声明的宏
#定义I2I_DEF(x,v)模板结构int2int{static const int value=v;};
//定义
I2I_DEF(2,5)I2I_DEF(7912958)I2I_DEF(55100)//等等。
//使用
#包括
int main()
{
STD::CUT< P>作为补充,如果需要二进制搜索实现,不要忽略C++标准库。以下是使用均衡器算法(对于代码质量稍差)道歉的结构类型数组中的一个
#包括
#包括
使用名称空间std;
结构{
int k,v;
};
bool算子>t.k;
S*valend=&values[0]+sizeof(values)/sizeof(S);
对位置=相等的范围(&值[0],值,t);
如果(位置第一!=位置第二){
cout v还有一种被称为“xmacros”的技术,它也是一种很好的方法,可以完全实现您所说的内容。但是,很容易滥用这种技术,因此我始终建议您谨慎使用。请查看:
基本要点是,您有一个文件,其中列出了映射,比如foo.txt,如下所示:
地图(2,5)
地图(7912958)
然后定义一个宏映射(a,B),它接受这两个参数并为您进行初始化。如果您愿意,您甚至可以通过在文件的每个包含之间重新定义宏来多次执行此操作。然后要添加更多映射,只需将它们添加到foo.txt并重新编译。它非常强大,可以用于许多不同的事情。如果您不想出于任何原因使用映射,(例如,您只想使用在编译时设置的数组)
pair< int, int > map_array[2] = { make_pair(2, 5), make_pair(79, 12958) };
map< int, int > theMap( &map_array[0], &map_array[2] ); // sorts the array
assert ( theMap[ 2 ] == 5 );
// template to specialize
template<int T> struct int2int {};
// macro for simplifying declaration of specializations
#define I2I_DEF(x, v) template<> struct int2int<x> { static const int value = v; };
// definitions
I2I_DEF(2, 5) I2I_DEF(79, 12958) I2I_DEF(55, 100) // etc.
// use
#include <iostream>
int main()
{
std::cout << int2int<2>::value << " " << int2int<79>::value << std::endl;
return 0;
}
#include <algorithm>
#include <iostream>
using namespace std;
struct S {
int k, v;
};
bool operator <( const S & a, const S & b ) {
return a.k < b.k;
};
// must be sorted in key order
S values[] = {{42,123},{666,27}};
int main() {
S t;
cin >> t.k;
S * valend = &values[0] + sizeof(values) / sizeof(S);
pair <S*,S*> pos = equal_range( &values[0], valend , t);
if ( pos.first != pos.second ) {
cout << pos.first->v << endl;
}
else {
cout << "no" << endl;
}
}
#include <windows.h>
#include <cstdlib>
#include <functional>
#include <algorithm>
#include <iostream>
using namespace std;
struct s { int a; int b; };
s theMap[] = { {2, 5}, {79, 12958 } };
struct match_key : public unary_function<s, bool>
{
match_key(int key) : key_(key) {};
bool operator()(const s& rhs) const
{
return rhs.a == key_;
}
private:
int key_;
};
int main()
{
size_t mapSize = sizeof(theMap)/sizeof(theMap[0]);
s* it = find_if(&theMap[0], &theMap[mapSize], match_key(79));
cout << it->b;
return 0;
}
#include <iostream>
#include <boost/assign.hpp>
int main()
{
typedef std::map< int, int > int2int_t;
typedef int2int_t::const_iterator int2int_cit;
const int2int_t theMap
= boost::assign::map_list_of
( 2, 5 )
( 79, 12958 )
;
int2int_cit it = theMap.find( 2 );
if ( it != theMap.end() )
{
const int result = it->second;
std::cout << result << std::endl;
}
}