关于回旋矩阵的几点思考 (数组-不使用数组)




关于回旋矩阵的几点思考

(数组-不使用数组)





某日,友人出题,要求 N*N的回旋矩阵的输出。

回旋矩阵,顾名思义,就是从外圈数字由大到小旋转到内圈的N阶矩阵

例如 :

    1   2   3   4   5

  16  17  18  19   6

  15  24  25  20   7

  14  23  22  21   8

  13  12  11  10   9

便是一个5*5的回旋矩阵。

对于这类问题,首先想到的是通过数组进行输出,现在数组中对各个位置的数进行排列,再由for循环对数组进行输出操作。如此思路清晰,代码明了,也不易出错。


#include <stdio.h>


#define N 16    //在此定义 矩阵的大小



int main(int argc, const char * argv[])

{


    int a[N][N] = {0};

    int i ,j ,x ,y ,m = 0;          //x y


    

    //计算部分

    for ( x = 0 ; x < N / 2 ; x++) {  //x是下限

        

        y = N - x - 1;   // y是上限

        

        

        

        if ( m == N * N) {

            break;

        }

        

        for ( i = x ; i < y  ; i++) {

            m++;

            a[i][x] = m;

        }

        


        if ( m == N * N) {

            break;

        }


        

        for ( i = x ; i < y ; i++ ) {

            m++;

           a[y][i] = m;

        }

        

        if ( m == N * N) {

            break;

        }


        for ( j = y  ; j > x ; j-- ){

            m++;

            a[j][y] = m;

        }

        

        if ( m == N * N) {

            break;

        }


        

        for ( j = y  ; j > x  ; j-- ){

            m++;

            a[x][j] = m;

        }

        

    }

    

    

    if (  N % 2 != 0) {

        int r = N / 2 ;

        a[r][r] = N * N;     //判读是否奇数 消除以上打表方法的小BUG

    }

    

    

    //打印部分

    

    for (i = 0 ; i < N ; i++) {

        for ( j = 0 ; j < N ; j++) {

            printf("%4d ", a[j][i]);

        }

        printf("\n\n");

    }

    

    return 0;


}


此处使用宏定义定义阶层N的值,算是偷了一点懒,若需手动录入N的大小,可以先建一个100*100的二位数组(10*10)也可,再将读入的数的值赋值给N,代码几乎相同,此处不再赘述。

此处思路是大环套小环的“嵌套”思路,即由外圈向内,逐圈进行计算,得益于数组可以先计算再输出的所谓优点,可以先计算出每一圈各个位置的每个数之后,再进行整体的输出。这里的方法更将每一环切分为4小段,再对每一段上的每一个数进行填充。其中N为奇数时因为for循环判断的机制,所以出现了一个Bug,导致最中心的数无法进行填充,最后通过特殊法对N进行判断,填充了中心的缺口。最后以二重for循环对二维数组进行打印输出。

这里的方法并不是非常的好,大家肯定有更好的办法。那么能不能不用数组呢?办法是有的。


#include <iostream>

#include <iomanip>


#define max(a,b)        (((a) > (b)) ? (a) : (b))

#define min(a,b)        (((a) < (b)) ? (a) : (b))

using namespace std;


int matrix(int i, int j, int n);


int main(int argc, const char * argv[])

{

    int n, i, j;

    

    cout << "Please input n:";

    cin >> n;

    

    for (j = 0; j < n; j++) {

        for (i = 0; i < n; i++) {

            cout << setw(4) <<matrix(j, i, n);

        }

        cout << endl <<endl;

    }

    

    return 0;

}


int matrix(int i, int j, int n)

{

    int m, a, l;

    

    m = min( min( i, n-1-i ), min( j, n-1-j ) );  //计算在第几环

    

    i -= m;

    j -= m;

    

    a = 1 + 4*m*(n-m);        //首元素

    

    l = n - 2*m;                   // 环边长

    

    if (i == 0)

        return a+j;

    else if (j == 0)

        return a + 4*(l-1) - i;

    else if (i == l-1)

        return a + 4*l - 3 - l - j;


    return a + l-1 + i;


}


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值