【问题标题】:C++ matrix - min/max elementsC++ 矩阵 - 最小/最大元素
【发布时间】:2014-04-08 06:17:05
【问题描述】:

我实现了可以找到矩阵元素的 c++ 程序: 哪个是行的最大元素,同时是其列的最小元素,或者 - 行的最小元素,同时是其列的最大元素。 例如,我们有 data.txt 文件:

  • 4
  • 7 8 9 10
  • 6 5 4 11
  • 5 0 1 12
  • 4 2 7 13
  • -

其中 4 是 n - 矩阵大小 (4x4),7 和 10 是这些数字。

代码如下:

#include <iostream>
#include <fstream>

using namespace std;
int main(){

    ifstream is;
    ofstream os;
    int n;

    is.open("data.txt");
    if (is.fail()){
        cout << "Failed to open data file" << endl;
        exit(-1);
    }
    is >> n;

    double **matrix;
    matrix = new double*[n];
    for (int i = 0; i < n; i++){
        matrix[i] = new double[n];
    }

    for (int i = 0; i < n; i++){
        for (int j = 0; j < n; j++){
            is >> matrix[i][j];
        }
    }

    double* maxROW = new double[n];
    double* minROW = new double[n];
    for (int i = 0; i < n; i++){
        maxROW[i] = matrix[i][0];
        minROW[i] = matrix[i][0];
        for (int j = 0; j < n; j++){
            if (matrix[i][j] > maxROW[i]){
                maxROW[i] = matrix[i][j];
            }
            if (matrix[i][j] < minROW[i]){
                minROW[i] = matrix[i][j];
            }
        }
    }

    double* maxCOLUMN = new double[n];
    double* minCOLUMN = new double[n];
    int x = 0;
    for (int i = 0; i < n; i++){
        maxCOLUMN[i] = matrix[0][x];
        minCOLUMN[i] = matrix[0][x];
        for (int j = 0; j < n; j++){
            if (matrix[j][i] > maxCOLUMN[i]){
                maxCOLUMN[i] = matrix[j][i];
            }
            if (matrix[j][i] < minCOLUMN[i]){
                minCOLUMN[i] = matrix[j][i];
            }

            if (j == n - 1) x++;
        }
    }

    int k = 0;
    for (int i = 0; i < n; i++){
        for (int j = 0; j < n; j++){
            if (maxROW[i] == minCOLUMN[j]){
                k++;
            }
            if (minROW[i] == maxCOLUMN[j]){
                k++;
            }
        }
    }

    double* matrixNUM = new double[k];
    int l = 0;
    for (int i = 0; i < n; i++){
        for (int j = 0; j < n; j++){
            if (maxROW[i] == minCOLUMN[j]){
                matrixNUM[l] = matrix[i][j];
                l++;
            }
            if (minROW[i] == maxCOLUMN[j]){
                matrixNUM[l] = matrix[i][j];
                l++;
            }
        }
    }

    cout << "Matrix numbers: " << endl;
    for (int i = 0; i < k; i++){
        cout << matrixNUM[i] << ", ";
    }
    cout << endl;

    for (int i = 0; i < n; i++){
        delete[] matrix[i];
    }
    delete[] matrix;
    delete[] maxCOLUMN;
    delete[] minCOLUMN;
    delete[] maxROW;
    delete[] minROW;
    delete[] matrixNUM;
    return 0;
}

问题:我想知道我的代码是否是“脏”代码?因为我总是热衷于让一切变得如此困难,只要有可能让它变得容易。是否有不同的方式,也许更容易,也许更容易理解的方式来实现这样的任务?提前感谢谁会发现此代码中的错误。

【问题讨论】:

  • 使用vectors 会清理你的代码,但这不是必需的
  • 我认为你可以做的最重要的改变是将其分解为函数,例如,displayMatrix(...) 函数、findNUMs(...) 函数...
  • 函数也不是必须的。你的代码很好。您可以通过仅在一对嵌套 for 循环中计算行/列的最小/最大值来提高性能。但是复杂度还是一样的。
  • 这看起来像是 stackexchange 的 codereview 部分的问题。

标签: c++ matrix


【解决方案1】:
int main(){

  std::ifstream is;
  std::ofstream os;

  is.open("data.txt");
  if (is.fail()){
    std::cerr << "Failed to open data file\n";
    exit(-1);
  }
  int n;
  is >> n;

  if (n <= 0)
  {
    std::cerr << "Negative matrix size, aborting\n";
    exit(-1);
  }
  std::vector< std::vector<double> > matrix( n, std::vector<double>(n) );

  for (int i = 0; i < n; i++){
    for (int j = 0; j < n; j++){
      is >> matrix[i][j];
    }
  }

  std::vector<double> maxROW(n);
  std::vector<double> minROW(n);
  for (int i = 0; i < n; i++){
    auto minmax = std::minmax_element( matrix[i].begin(), matrix[i].end() );
    maxROW[i] = *minmax.second;
    minROW[i] = *minmax.first;
  }

  std::vector<double> maxCOLUMN(n);
  std::vector<double> minCOLUMN(n);
  for (int i = 0; i < n; i++){
    maxCOLUMN[i] = matrix[0][i];
    minCOLUMN[i] = matrix[0][i];
    for (int j = 1; j < n; j++){
      maxCOLUMN[i] = std::max( maxCOLUMN[i], matrix[j][i] );
      minCOLUMN[i] = std::min( minCOLUMN[i], matrix[j][i] );
    }
  }

  std::vector<double> matrixNUM;
  for (int i = 0; i < n; i++){
    for (int j = 0; j < n; j++){
      if (maxROW[i] == minCOLUMN[j]){
        matrixNUM[l].push_back(matrix[i][j]);
      }
      if (minROW[i] == maxCOLUMN[j]){
        matrixNUM[l].push_back(matrix[i][j]);
      }
    }
  }

  std::cout << "Matrix numbers: " << endl;
  for (double num:matrixNUM)
    std::cout << num << ", ";
  }
  std::cout << "\n";
}

可能有错别字,但上面应该一样快,而且代码更少。

它确实使用了一些 C++11 特性。

【讨论】:

    【解决方案2】:

    随机说明,C++11 的变长数组处理仍然有繁琐的方面,但是:

    int n;          is >> n;
    
    double (&matrix)[n][n] = *(double(*)[n][n])(new double[n*n]);
    
    for (auto &r:matrix)
            for (auto &c:r)
                    is >> c;
    
    // ...
    
    delete[] &matrix
    

    堆得很好。

    【讨论】:

    • 在引用中存储资源?嗯。只需for(auto&amp; r:*matrix)* 放在那里而不是&amp; 放在delete 中。你能保证double[n][n] 的布局与double[n*n] 兼容吗? (在实践中,是的,但我还没有把这个保证从标准中挑逗出来......)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-13
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 2014-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多