我想用C或C ++生成一个循环矩阵。
如何生成下面的矩阵,n = 3?
1 2 3
8 9 4
7 6 5
答案 0 :(得分:3)
我前几次做过......
伪代码:
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 :(得分:1)
作为@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];
};
答案 2 :(得分:1)
这个问题在微软的笔试中提出。 因此,考虑给出完整的代码。
下面的代码适用于运行时给出的任意数量的行和任意数量的列。 无需对尺寸进行硬编码。
#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);
}
答案 3 :(得分:0)
#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;
}
答案 4 :(得分:0)
首先让你的矩阵变空。在我的例子中,我在std :: pair上使用std :: map,但你也可以使用2维数组。我使用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&lt; 0或&gt; =矩阵的大小)。
如果您仍在矩阵中,请在地图中使用std :: find查看此条目是否已填写:
if (matrix.find(nextPosition)!=matrix.end()) /* valid position */
如果碰到矩阵的边界或碰到已填入的条目,请再次取出当前位置,增加currentMovePosition以更改方向并再试一次。 如果改变方向,请务必将currentMovePosition包裹起来。
currentMovePosition = (currentMovePosition + 1) % 4;
继续这样做,直到矩阵完全填满。
要确定矩阵是否已完全填充,您可以检查所有4个方向是否都移动到已填充的元素,但更简单的方法是简单计算填充单元格的数量,如果它等于大小*大小则停止矩阵。
答案 5 :(得分:-1)
在“圆形”矩阵中,它的“中间”也是圆形的, 除了它不以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); }