草庐IT

c++ - 矩阵中独立对角线的总和

coder 2023-11-16 原文

我目前正在备考,我正在尝试处理动态矩阵。我遇到了一个关于计算矩阵的每条对角线之和的问题,该矩阵的值和大小由用户选择。 我的程序的目的是打印,多亏了一个函数,其参数是矩阵及其大小,每个对角线和的值。我将向您展示代码并对其进行深入描述。

----------------
| 52 | 35 | 5  |  Example of matrix.
----------------  Imagine the first diagonal to be the one which goes right-to-left
| 2  | 71 | 1  |  and only consists in the number "47".
----------------  The second diagonal would be the one which goes right-to-left and
| 3  | 60 | 25 |  consists in the number "15" and "79".
----------------  So to get the sum of the second diagonal it would be:
| 79 | 55 | 98 |     
----------------  sum = m[n_rows - 1][diag - 2] + m[n_rows - 2][diag - 1]
| 47 | 15 | 66 | 
----------------  When diag > columns, in order to avoid error regarding matrix size,
                  I should lower the quantity "n_rows - 1" by the quantity "diag - n_columns".

根据我的描述,这是我想做的:

void diag_matrix(int** m, int righe, int colonne){//righe = rows, colonne = columns. 
//M is the matrix.

// diag is the number of the diagonal I'm considering.
    for(int diag = 1; diag < (righe + colonne); diag++){ 

        int sum = 0;// the sum
        int i = 0;// the counter of the cicle
        int l = 0;// this is the value to riallign the row in case diag > column
        int temp = diag;//I use this variable not to modify the value of diag.

        // What I want is: when the column-index/row-index of the matrix reaches 0, the cicle will interrupt (after final iteration);
        while(righe - i - l - 1 > 0 || diag - 1 - i > 0){

            if (diag > colonne){//this condition changes l-value only if diag value is greater than column. Explanation outside the code
                l = diag - colonne;//this is the value to subtract to row-index
                temp = colonne;//this position is necessary to set column-index to its maxium.
            }

            sum = sum + m[righe - 1 - l - i][temp -1 - i];//pretty clear I think.
            i++;//the i is incremented by one.

        }// end of while-statement

        cout << "Somma Diagonale " << diag << " = " << sum << ".\n";

    }// end of for-statement

}//end of function declaration

显然是行不通的,但我想不出问题所在。

最佳答案

(这里本来有一段话,但仔细一看,你并没有犯它说的错误。)

由于您没有发布到代码审查,这里有一个解决方案而不是详细的代码审查。 (如果你想让原来的方法起作用,我建议在调试器中单步执行它并检查你的变量首先在哪里获得错误值。)它有很多样板来编译和运行,但是您最感兴趣的部分是 diag_sums() 及其注释。

这里的一个想法是使用 OOP 来自动检查数组访问的边界。后者对于捕获逐一错误等非常重要。如果你愿意,你可以在生产中关闭它,但你真的不想在你的程序有缓冲区溢出时关闭警告。这里的其他优化包括数据访问的局部性,以及操作的强度降低:我们可以简单地预先计算每条对角线的长度,而不是检查每次迭代是否碰到右边缘和下边缘。

由于M行矩阵a的对角线数k的定义等价于:所有元素a[i] [j] 使得 M - k = i - j,该算法确保通过保持不变性来保持正确性,每当我们将 ij 都加 1 时,从 ij为0,每当i = Mj = N时停止,即遍历每一步从左边缘或上边缘到右边缘或下边缘的对角线,以先到者为准。

#include <assert.h>
#include <iostream>
#include <stddef.h>
#include <stdlib.h>
#include <utility>
#include <vector>

using std::cin;
using std::cout;

template <typename T>
  class matrix {
    public:
      matrix( const ptrdiff_t rows,
              const ptrdiff_t cols,
              std::vector<T>&& elems )
        : rows_(rows), cols_(cols), elems_(elems)
      {
        assert( rows_ > 0 );
        assert( cols_ > 0 );
        assert( elems_.size() == static_cast<size_t>(rows_*cols_) );
      }

      matrix( const ptrdiff_t rows,
              const ptrdiff_t cols,
              const std::vector<T>& elems )
        : matrix( rows, cols, std::move(std::vector<T>(elems)) )
      {}

      matrix( const matrix<T>& ) = default;
      matrix( matrix<T>&& ) = default;
      matrix& operator= ( const matrix<T>& ) = default;
      matrix& operator= ( matrix<T>&& ) = default;

      T& operator() ( const ptrdiff_t m, const ptrdiff_t n )
      {
        assert( m >= 0 && m < rows_ );
        assert( n >= 0 && n < cols_ );
        return elems_[static_cast<size_t>(m*cols_ + n)];
      }

      const T& operator() ( const ptrdiff_t m, const ptrdiff_t n ) const
      {
       /* Because this call does not modify any data, and the only reason the
        * member function above cannot be const is that it returns a non-const
        * reference to an element of elems, casting away the const qualifier
        * internally and then returning a const reference is a safe way to
        * re-use the code.
        */
        matrix<T>& nonconst = *const_cast<matrix<T>*>(this);
        return nonconst(m,n);
      }

      ptrdiff_t rows() const { return rows_; }
      ptrdiff_t cols() const { return cols_; }

    private:
      ptrdiff_t rows_;
      ptrdiff_t cols_;
      std::vector<T> elems_;
  };

template<typename T>
  std::ostream& operator<< ( std::ostream& out, const matrix<T>& x )
  /* Boilerplate to print a matrix. */
  {
    const ptrdiff_t m = x.rows(), n = x.cols();

    for ( ptrdiff_t i = 0; i < m; ++i ) {
      out << x(i,0);
      for ( ptrdiff_t j = 1; j < n; ++j )
        out << ' ' << x(i,j);

      out << '\n';
    } // end for

    return out;
  }

using elem_t = int;

std::vector<elem_t> diag_sums( const matrix<elem_t>& a )
/* Return a vector of all the diagonal sums of a.
 *
 * The first diagonal sum is a(rows-1,0)
 * The second is a(rows-2,0) + a(rows-1,1)
 * The third is a(rows-3,0) + a(rows-2,1) + a(rows-1,2)
 * And so on.  I.e., the kth diagonal is the sum of all elements a(i,j) such
 * that i - j == rows - k.
 *
 * If a is a M×N matrix, there are M diagonals starting in column zero, and
 * N-1 diagonals (excluding the one containing a(0,0) so we don't count it
 * twice) starting in row 0.  We process them bottom to top, then left to
 * right.
 *
 * The number of elements in a diagonal starting at a(i,0) is min{M-i, N}.  The
 * number of elements in a diagonal starting at a(0,j) is min{M, N-j}.  This is
 * because a diagonal stops at either the bottom edge or the left edge of a.
 */
{
  const ptrdiff_t m = a.rows(), n = a.cols();
  std::vector<elem_t> result;
  result.reserve( static_cast<size_t>(m + n - 1) );

  for ( ptrdiff_t i = m-1; i > 0; --i ) {
    elem_t sum = 0;

    const ptrdiff_t nk = (m-i) < n ? (m-i) : n;
    for ( ptrdiff_t k = 0; k < nk; ++k )
      sum += a(i+k, k);

    result.emplace_back(sum);
  } // end for i

  for ( ptrdiff_t j = 0; j < n; ++j ) {
    elem_t sum = 0;

    const ptrdiff_t nk = m < (n-j) ? m : (n-j);
    for ( ptrdiff_t k = 0; k < nk; ++k )
      sum += a(k, j+k);

    result.emplace_back(sum);
  } // end for j

  return result;
}

matrix<elem_t> read_input_matrix( const int row, const int column )
/* Reads in row*column consecutive elements from cin and packs them into a
 * matrix<elem_t>.
 */
{
  assert(row > 0);
  assert(column > 0);

  const ptrdiff_t nelements = row*column;
  assert(nelements > 0); // Check for overflow.

  std::vector<elem_t> result;
  result.reserve(static_cast<size_t>(nelements));

  for ( ptrdiff_t i = nelements; i > 0; --i ) {
    int x;
    cin >> x;
    assert(cin.good());
    result.push_back(x);
  }

  return matrix<elem_t>( row,
                         column,
                         std::move(result) );
}

template<typename T>
  bool print_sequence( const T& container )
  /* Prints the contents of a container in the format
   * "{47, 94, 124, 160, 148, 36, 5}".
   */
  {
    cout << "{";

    if ( container.begin() != container.end() )
      cout << *container.begin();

    for ( auto it = container.begin() + 1; it < container.end(); ++it )
      cout << ", " << *it;

    cout << "}\n";

    return cout.good();
  }

/* A simple test driver that reads in the number of rows, the number of
 * columns, and then row*columns int values, from standard input.  It
 * then passes the result to diag_matrix(), E.g.:
 *
 * 5 3
 * 52 35  5
 *  2 71  1
 *  3 60 25
 * 79 55 98
 * 47 15 66
 */
int main()
{
  int rows, columns;
  cin >> rows;
  cin >> columns;

  assert(cin.good());

  const matrix<elem_t> input_matrix = read_input_matrix( rows, columns );
  // cout << input_matrix; // Instrumentation.
  const std::vector<elem_t> sums = diag_sums(input_matrix);

  print_sequence(sums);

  return EXIT_SUCCESS;
}

您也可以只执行 print_sequence(diag_sums(read_input_matrix( rows, columns )))

关于c++ - 矩阵中独立对角线的总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48570937/

有关c++ - 矩阵中独立对角线的总和的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

    我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

  3. 旋转矩阵的几何意义 - 2

    点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度;     在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。

  4. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  5. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  6. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  7. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  8. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  9. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

    出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

  10. ruby - Ruby 中字符串运算符 + 和 << 的区别 - 2

    我是Ruby和这个网站的新手。下面两个函数是不同的,一个在函数外修改变量,一个不修改。defm1(x)x我想确保我理解正确-当调用m1时,对str的引用被复制并传递给将其视为x的函数。运算符当调用m2时,对str的引用被复制并传递给将其视为x的函数。运算符+创建一个新字符串,赋值x=x+"4"只是将x重定向到新字符串,而原始str变量保持不变。对吧?谢谢 最佳答案 String#+::str+other_str→new_strConcatenation—ReturnsanewStringcontainingother_strconc

随机推荐