【问题标题】:Extract diagonal of a matrix提取矩阵的对角线
【发布时间】:2021-09-30 19:47:54
【问题描述】:

我正在使用 C++ 的 std 进行学校锻炼,我想找到一种方法来使用 std::copy 提取矩阵的对角线。这就是我想出来的,但它给了我一个分段错误错误。我究竟做错了什么?是否有更多的 C++ 方法可以在不使用 for 循环的情况下执行此操作? 谢谢

#include<vector>
#include<algorithm> 
#include<iostream>
#include<iterator> 

int main () {

    std::vector<std::vector<int>> vec {{1,2,3},{3,4,5},{1,6,7} ;
    std::vector<int> vec1{0,0,0} ; 
    std::copy ( &vec[0][0], &vec[2][2], &vec1[0] ) ;

}


【问题讨论】:

  • 假设vec 中的数据像对应的数组一样存储(即int vec[3][3],这实际上并不能保证IIRC),那么您的复制将复制vec 的所有九个元素进入三元素向量vec1
  • 用一个简单的for 循环来做你需要的事情有什么问题?
  • 这里有一些问题可以帮助您自己找到解决方案:&amp;vec[0][0]&amp;vec[2][2] 的评估结果是什么?我的意思是类型,而不是值。基于这种类型,您认为copy() 会如何处理它?你能把copy() 翻译成一个循环吗?它会是什么样子?提取对角线的循环是什么样的?
  • 好吧,您可以编写一个自定义迭代器来沿对角线遍历矩阵并将其中的几个(开始和结束)提供给std::copy,但我很有信心这是 不是你应该在这里做的,更不用说这将是一个比单个循环更复杂的数量级的任务。
  • @Some程序员老兄 一个简单的for循环没有错,但我想学习一点STL。我经常看到使用 STL 中的一些奇异算法而不是 for 循环的一行代码的答案,我认为我可以做类似的事情,但可能情况并非如此。

标签: c++ algorithm c++11 std stdvector


【解决方案1】:

您遇到分段错误的原因是您使用副本的方式,您提供了无效参数。实际上并没有一种方法可以对角地遍历 2D 数组或向量(尽管如果您使用的是 2D 数组(不是向量),您可以给它一个彼此对角线的起点和终点,但它只会复制所有内容之间,而不仅仅是对角线)。

我建议只使用 for 循环,这没有什么问题。 (即使有一些复杂的方法可以让复制工作,for 循环已经足够清晰和快速)。

#include<vector>
#include<algorithm> 
#include<iostream>
#include<iterator> 

int main () {

    std::vector<std::vector<int>> vec {{1,2,3},{3,4,5},{1,6,7}} ;
    // std::vector<int> vec1{0,0,0} ; 
    // std::copy ( &vec[0][0], &vec[2][2], &vec1[0] ) ;

    std::vector<int> diagonal;
    for(uint i=0;i<vec.size();i++){
        diagonal.push_back(vec[i][i]);
    }
    
}

【讨论】:

    【解决方案2】:

    您没有标准的数组,数组的所有元素都连续地存储在其中。相反,您有一个 edge-vector 数组(维基百科称其为 Iliffe vector,尽管我从未听过任何人真正将其称为我自己)。因此,您的索引方法必须考虑到这一点。正如所指出的(在其他答案和 cmets 中),只有在 单个容器中工作的普通 迭代器 无法做到这一点。

    (边向量数组是一个锯齿状数组,其约束条件是所有指向的向量都具有相同的长度。)

    您可以使用 分段迭代器 将其索引为“单元”(如果您愿意,如 "Segmented Iterators and Hierarchical Algorithms" (Austern) (pdf) 中所述。但对于大多数简单的用例来说,这需要做很多工作,例如你描述的那个,一个简单的for循环就可以了(并且更容易理解和调试)。

    【讨论】:

      猜你喜欢
      • 2020-02-05
      • 1970-01-01
      • 1970-01-01
      • 2016-04-24
      • 1970-01-01
      • 2023-04-08
      • 2017-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多