【问题标题】:How to generate circular matrix?如何生成圆形矩阵?
【发布时间】:2010-11-11 12:22:47
【问题描述】:

我想用 C 或 C++ 生成一个循环矩阵。

对于 n = 3,我如何生成下面的矩阵?

1 2 3
8 9 4
7 6 5

【问题讨论】:

  • 请确定您是在谈论C 还是C++,因为每种情况下的解决方案都会非常不同。 (你可能还想提一下这是否是家庭作业——它看起来很熟悉......)
  • @Paul:这里的困难部分是如何巧妙地为索引生成坐标,现在如何将它们存储在二维矩阵中。所以就在这种情况下,语言确实或多或少无关紧要。
  • 这闻起来像homework...
  • @Konrad: 是的,但是如果 2D 矩阵本身的创建在每种情况下都会非常不同,并且 OP 确实需要特定的 C 或 C++ 实现,那么可能会浪费一些时间以及由此产生的来回
  • @Hiren Dabhi,你需要说出你做了什么,以及问题是关于存储还是填充矩阵。

标签: c++ c matrix


【解决方案1】:

我之前做过...

伪代码:

min_x = 0;
min_y = 0;
max_x = X;
max_y = Y;

while(!all_fields_filled){

  // move right  -------------------------
  for(i = min_x; i <= max_x; i++){
    array[min_y][i] = fields_number;
    fields_number++;
  }

  min_y++

  // it is important to check that condition after each for
  // (our total field number could be not divided by 4)
  if(filled_fields == fields_amount) break;
  // edn "move right" procedure -----------


  // ETC. for move DOWN, next LEFT and UP
  // remember to increase min_x/min_y and decrease max_y/max_y

}

【讨论】:

  • +1 只为一个相当明显的硬件问题提供伪代码。
【解决方案2】:

作为@Rin 答案的替代方案,您可以考虑以线性顺序存储矩阵,然后在访问它时重新映射索引。如果您使用 C++,则可以通过访问器函数封装此重新映射,例如:

class WierdMatrix
{
public:
    ...

    int get(int x, int y) const
    {
        /* Mapping goes here */
        return M_[x_mapped][y_mapped];
    }
private:
    int M_[3][3];
};

【讨论】:

    【解决方案3】:

    这个问题是在微软笔试中提出的。 因此考虑给出完整的代码。

    以下代码适用于运行时给出的任意数量的行和任意数量的列。 无需对尺寸进行硬编码。

    #include <iostream>
    using namespace std;
    
    //Prints matrix in Spiral fashion.
    void printSpiral(const int& numRows, int& numCols)
    {
        int **v = new int*[numRows]; //Allocation for rows
        for(int i = 0; i< numRows; i++)   //Allocation for columns
        {
            v[i] = new int[numCols];
        }
        int curRow = 0, curCol = -1; //for storing current position while moving.
         //Below variables are for remembering boundaries
         //That is already traversed row/column
         int minRowLimit = -1, maxRowLimit = numRows;
         int minColLimit = -1, maxColLimit = numCols;
    
        int num = 1; //Start filling from 1
         //Total number of elements to be filled
        int totalElements = numRows * numCols; 
        while(1)
        {
            while(curCol < maxColLimit-1)  //Move right
            {
                ++curCol;
                v[curRow][curCol] = num;
                num++;
            }
            if(num > totalElements) break; //Filling completed.
            minRowLimit++;
    
            while(curRow < maxRowLimit-1) //Move down
            {
                ++curRow;
                v[curRow][curCol] = num;
                num++;
            }
            if(num > totalElements) break; //Filling completed.
            maxColLimit--;
    
            while(curCol > minColLimit+1)     //Move left
            {
                --curCol;
                v[curRow][curCol] = num;
                num++;
            }
            if(num > totalElements) break; //Filling completed.
            maxRowLimit--;
    
            while(curRow > minRowLimit+1)  //Move up
            {
                --curRow;
                v[curRow][curCol] = num;
                num++;
            }
            if(num > totalElements) break; //Filling completed.
            minColLimit++;
        }
         //Print the matrix for verification.
        for(int i = 0; i < numRows; i++)
        {
            for(int j=0; j < numCols; j++)
            {
                cout<<v[i][j]<<"\t";
            }
            cout<<endl;
        }
    
         //Clean up.
        for(int i = 0; i<numRows; i++)
        {
            delete []v[i];
        }
        delete []v;
    }
    
    int main()
    {
         //Enter rows and columns according to your choice 
         //regarding matrix dimensions.
        int nRows, nCols;
        cout<<"Enter number of rows"<<endl;
        cin>>nRows;
        cout<<"Enter number of cols"<<endl;
        cin>>nCols;
        printSpiral(nRows, nCols);
    }
    

    【讨论】:

    • 我不确定 Microsoft 笔试中出现此问题对您提供完整代码的决定有何影响。一般来说,如果我们没有立即得到解决方案,我们会学得最好。不过,感谢您在代码中提供一些解释。
    【解决方案4】:

    首先让你的矩阵为空。在我的示例中,我在 std::pair 上使用了 std::map,但您也可以使用二维数组。我使用 std::map 是因为它更容易看到元素何时丢失。

    typedef std::pair<int,int> Coordinate;
    typedef std::map<Coordinate,int> Matrix;
    

    然后制作一个包含您想要移动的不同方向的集合。 如果首先要向右移动,则意味着将 X 加 1,然后保持 Y 不变。然后我们向下移动,这意味着将 Y 加 1 并离开 X。

    typedef std::vector<Coordinate> Moves;
    Moves moves;
    moves.push_back(std::make_pair(1,0));
    moves.push_back(std::make_pair(0,1));
    moves.push_back(std::make_pair(-1,0));
    moves.push_back(std::make_pair(0,-1));
    

    初始化您的起始坐标,它们会移动,直到您到达“边界”。边界要么是边框,要么是已经填充的单元格。

    Coordinate currentPosition = std::make_pair(0,0);
    int currentValue = 1;
    int currentMovePosition = 0;
    

    然后在一个循环中(但我把这个作为练习留给你写出来:-))只需填写矩阵:

    matrix[currentPosition] = currentValue;
    ++currentValue;
    

    并移动到下一个位置;

    Coordinate nextPosition = currentPosition;
    nextPosition.first += moves[currentMovePosition].first;
    nextPosition.second += moves[currentMovePosition].second;
    

    检查 nextPosition 以查看您是否在矩阵之外(nextPosition.first/second = 矩阵大小)。

    如果您仍在矩阵内,请在地图中使用 std::find 以查看该条目是否已被填写:

    if (matrix.find(nextPosition)!=matrix.end()) /* valid position */
    

    如果碰到矩阵的边界或者碰到一个已经填好的条目,再次取当前位置,递增 currentMovePosition 以改变方向,然后重试。 如果您改变方向,请务必环绕 currentMovePosition。

    currentMovePosition = (currentMovePosition + 1) % 4;
    

    继续这样做,直到矩阵完全填满。

    要判断矩阵是否被完全填满,可以检查是否所有4个方向都移动到已经被填满的元素,但更简单的方法是简单地计算被填满的单元格的数量,如果等于size*size则停止矩阵。

    【讨论】:

      【解决方案5】:
      #define N 3
      
      int coords[N*N];
      
      void printn() {
        int i,j;
        for ( i = 0 ; i < N ; i++ ) {
          for ( j = 0 ; j < N ; j++) {
            printf("%2d ",coords[i*N+j]);
          }
          printf("\n");
        }
      }
      
      void gennum(int n,int ox,int oy,int lx) {
        int i,j,k,l;
        for ( j = ox; j < n ;j++) {
          coords[ (oy*N)+j ]=  j-ox + lx;
        }
      
        for ( i = oy+1; i < n ;i++) {
          coords[ (i*N) + n-1 ] = (i-1) -(oy) + (j-ox) + lx;
        }
      
        for ( l = n-2 ; l >=ox ;l--) {
          coords[ (n-1)*N + l ] = (n-l-2)+ (i-1) -(oy) + (j-ox)  + lx ;
        }
      
        for ( k = n-2; k >= oy+1 ;k--) {
          coords[ (k*N)+ox ] = (n-k-2)+(n-l-2)+ (i-1) -(oy) + (j-ox) + lx ;
        }
        if ( n > 2 ) {
          gennum(n-1,ox+1,oy+1,(n-k-2)+(n-l-2)+ (i-1) -(oy) + (j-ox) + lx); 
        }
      }
      
      int main() {
        memset(coords,0,N*N*sizeof(int));
        gennum(N,0,0,1);
        printn();
        return 0;
      }
      

      【讨论】:

      • 选择一个代码块,然后使用 ctrl-k 或 101 按钮缩进它。
      • 来自homework question guidelines(元):“尝试提供能够引导提问者朝着正确方向前进的解释……如果您认为不会提供完整的代码示例,通常最好不要提供用你最好的判断来帮助学生。”你的判断是你自己的,但通常只写完整的代码并不能帮助理解
      • 除了@Jefromi 的评论,尤其是在没有给出解释的情况下,即使对于非家庭作业问题,这也是一个糟糕的答案。
      【解决方案6】:

      在一个“圆形”矩阵中,它的“中间”也是圆形的, 除了它不是以 1 开头的。 所以绕着外围跑,然后递归。

      void    cmat_step( int** M, int a, int i, int j, int dim)
      {    
      int    k;
          /* fill perimeter */
          for( k=0; k<dim; ++k)        M[i][j+k]       = a++;
          for( k=1; k<dim; ++k)        M[i+k][j+dim-1] = a++;
          for( k=dim-2; k>=0; --k)     M[i+dim-1][j+k] = a++;
          for( k=dim-2; k>=1; --k)     M[i+k][j]       = a++;
          if ( dim >=2)    
          {    /* fill middle */
              cmat_step( M, a, i+1,  j+1, dim-2);
          }
      }
      void    cmat( int** M, int dim)    {    cmat_step( M, 1, 0, 0, dim);    }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-10-09
        • 2022-01-15
        • 1970-01-01
        • 2020-01-15
        • 1970-01-01
        • 2013-11-05
        • 1970-01-01
        • 2022-01-05
        相关资源
        最近更新 更多