Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 阵列与映射的性能_C++ - Fatal编程技术网

C++ 阵列与映射的性能

C++ 阵列与映射的性能,c++,C++,我必须在一个大数组中的元素子集上循环,其中每个元素指向另一个元素(问题来自于在一个大图形中检测连接的组件) 我的算法如下: 1.考虑第一元素 2.将下一个元素视为前一个元素所指向的元素。 3.循环,直到没有发现新元素 4.考虑下一个元素在1-3中没有考虑过,回到1。 注意,要考虑的元素数量远小于元素总数。 就我现在所见,我可以: //create a map of all element, init all values to 0, set to 1 when consider map<i

我必须在一个大数组中的元素子集上循环,其中每个元素指向另一个元素(问题来自于在一个大图形中检测连接的组件)

我的算法如下: 1.考虑第一元素 2.将下一个元素视为前一个元素所指向的元素。 3.循环,直到没有发现新元素 4.考虑下一个元素在1-3中没有考虑过,回到1。 注意,要考虑的元素数量远小于元素总数。

就我现在所见,我可以:

//create a map of all element, init all values to 0, set to 1 when consider
map<int,int> is_set; // is_set.size() will be equal to N
我知道访问map中的键是O(logn),而它只是数组的常数,但我不知道malloc在创建时是否更昂贵,同时它还需要更多内存?

如果有疑问,衡量两种备选方案的性能。这是确定哪种方法最适合您的应用程序的唯一方法

也就是说,一次性的大型malloc通常并不十分昂贵。另外,尽管map是O(logn),但根据我的经验,大O隐藏了一个相对较大的常量因子,至少对于
std::map
实现是这样。在这种情况下,如果发现数组方法更快,我不会感到惊讶,但唯一确定的方法是测量

请记住,虽然映射没有大的预先内存分配,但在对象的整个生命周期中它有许多小的分配(每次插入新元素时,您都会得到另一个分配,每次删除元素时,您都会得到另一个空闲分配)。如果您有很多这样的代码,那么可能会导致堆碎片化,这可能会对性能产生负面影响,具体取决于您的应用程序可能同时执行的其他操作

我知道访问map中的键是O(logn),而它只是数组的常量,但我不知道malloc在创建时是否更昂贵,同时它还需要更多内存

地图中的每个条目都是动态分配的,因此,如果动态分配是一个问题,那么它在地图中将是一个更大的问题。对于数据结构,您可以使用位图而不是int的普通数组。在32位
int
s的体系结构中,这将使阵列的大小减少32倍,在大多数情况下,将索引映射到阵列的额外成本将远小于额外内存的成本,因为结构更紧凑,可以容纳更少的缓存线


还有一些其他的事情要考虑,如集合中元素的密度是否小。如果条目很少(即图形稀疏),则任一选项都可以。作为最后一个选项,您可以使用向量
pair
手动实现映射,并将其缩短,然后使用二进制搜索。这将减少分配的数量,在排序时产生一些额外的成本,并提供比map更紧凑的O(logn)解决方案。尽管如此,我还是会尝试使用位掩码。

如果索引搜索适合您的需要(如常规C样式数组提供的),则可能
std::map
不适合您。相反,如果需要动态运行时分配或<代码> STD::数组< /代码>,如果您的集合是固定大小的,并且您只需要最快的边界安全替代C样式指针,请考虑使用<代码> STD::Vector < /C>。
你可以找到更多关于这方面的信息。

没有那么多解决方案,你可以做
int*is_set=new int[total_size]而不是使用MaloC .@ JojththMas,它是否改变了什么,因为它只是块内存的分配?在你的情况下,没有,但是你的问题被标记为C++,这就是 C++风格> /COD>。不过malloc和new之间是有区别的。@josephthomas:在这种情况下,
new
malloc
之间的区别并不重要,因为OP正在分配一个POD数组。我知道,但一个典型的建议是遵守“语言指定的编码标准”.我对位图的这种方法不太熟悉。我将寻找关于这方面的信息和建议,听起来是个有趣的想法。Thx@Arno:已经有一些类型实现了位图(包括
std::bitset
(固定大小)和臭名昭著的
std::vector
),基本上每个值只映射到内部表示中的一位。要设置元素N,您需要更新位置(N/32)处的无符号整数,并设置(N%32)位。这提供了数据的紧凑表示。映射的分配不是一个问题,因为元素是有序的,所以我可以从映射的末尾以摊销的恒定时间迭代初始化。更让我困扰的是访问键的复杂性。@Arno:访问数组元素是O(1),这比访问map元素的O(logn)时间要好得多。再说一次,你最好的办法是测量。是的,为什么要把事情复杂化?如果您需要一个没有间隙的数字键,只要在运行时使用
std::array
(如果大小已知)或
vector
即可。你的钥匙是内置的。为此使用关联容器是对轮子的重新发明,但使其成为方形。
//create a (too) large array (total size), init to 0 the elements to consider
int* is_set = (int*)malloc(total_size * sizeof(int)); // is_set length will be total_size>>N