J. *_*Doe 69 c++ algorithm vector
在最近的一次采访中,我建议使用vector<pair<int,int>>over vector<vector<int>>,因为我们只想为向量中的每个条目存储两个值。vector<pair<int,int>>我说了一些“我们应该使用over vector<vector<int>>,因为后者比前者重”的话。
编码会议结束后,他们说使用对而不是向量是个好主意,并要求我详细说明之前所说的“更重”的含义。不幸的是,我无法详细说明。是的,我知道我们只能在一对中输入两个值,但在向量中可以输入更多值,并且当向量的大小==容量等时,该向量会自动调整大小,等等,但我应该如何回答他们的问题 - 为什么具体使用比vector<pair<int,int>> 更好vector<vector<int>>?在后一种情况下还做了哪些额外的事情?
Sam*_*hik 78
每个向量都是动态分配的单个连续内存区域。
假设您有 1000 个要使用的值。
std::vector<std::pair<int, int>>
Run Code Online (Sandbox Code Playgroud)
这将为您提供一个连续的内存块,用于存储 2000 个整数。
std::vector<std::vector<int>>
Run Code Online (Sandbox Code Playgroud)
这将为您提供可容纳 1000 个向量的单个连续内存块。
这 1000 个中的每一个std::vector都会为您提供另一个连续的内存块,仅存储两个整数。
因此,对于该数据结构,它将由分散在各处的 1001 个内存块组成,而不是一个连续的内存块。无论如何,您无法保证所有这些内存块都是连续的,一个接一个。
每个动态内存分配都是有代价的。成本相当小,但加起来非常非常快。一分钱很容易被忽视。一千便士应该足够你在星巴克买一杯咖啡了。
此外,现代 CPU 非常非常擅长访问连续的内存块。迭代单个连续的内存块以加起来 2000int秒将比对一千多个不连贯的内存部分进行相同的操作要快得多。
che*_*ner 30
您可以在不参考任何特定语言的情况下回答这个问题。该问题要求存储 2 元组序列。当然,您选择的类型应该能够存储 2 元组,但也不能存储其他大小的元组。因此,给定两种都能够存储所需值的类型,优先选择存储不需要的值的能力较差的一种。
vector<int>将允许您存储 2 元素向量,但也可以存储空向量、单元素向量、3 元素向量、4 元素向量等。pair<int,int>更精确,因为它只能存储两个值。
(并不是要低估已接受答案中提到的性能优势,只是为了提供使用精确类型的纯粹语义参数。)
all*_*llo 18
正如其他人提到的,std::vector<int>添加例如元素数量的计数器。
但你可以在面试中建议的一个有趣的方面是使用std::array<int, 2>. 它应该具有类似的成本,因为std::pair<int, int>它将数字存储在固定大小的数组中。一个优点是 API,它允许使用a[0]代替a.first,并且当您可能需要存储(例如,在添加一些新功能后每个条目三个值)时也更容易泛化。
nut*_*tax 14
为了简化解释,我们这样说
A[ a | b ] B[ c ] 意思是:a和b分别在块 A和块 Bc中。a 旁边是 b考虑到这一点,让我们看一个例子:内存使用情况 { { 1, 1 } , { 2, 2 }, ... }
为了std::vector<<std::vector<int>>
A[ size info | ptr to B ]B[ [ size info | ptr to C ] | [ size info | ptr to D ] | ... ]C[ 1 | 1 ]D[ 2 | 2 ]为了std::vector<std::pair<int, int>>
A[ size info | ptr to B ]B[ [ 1 | 1 ] | [ 2 | 2 ] | ... ]我认为这个例子非常清楚:在执行 时少了一层间接 std::vector<std::pair<int, int>>。意义
小智 7
向量是动态调整大小的数组。您牺牲了一些性能以获得动态调整大小的能力。
向量组成的向量 ( vector<vector<int>>) 的外部向量及其每个元素都会产生性能开销。对于向量对 ( vector<pair<int, int>>),则没有后者。一对始终具有固定大小,因此您不必担心必须根据需要调整其大小(并根据需要将其重新定位到内存中的另一个位置)。