码迷,mamicode.com
首页 > 其他好文 > 详细

第3章第1节练习题2 回形矩阵

时间:2016-04-29 16:26:40      阅读:129      评论:0      收藏:0      [点我收藏+]

标签:

问题描述

回型矩阵即使用二维数组完成来绕圈圈似的赋值,举例说明如下所示的形式即为回型数组。

技术分享

算法思想

就单纯的在二维数组中按照某种顺序输出连续的数字而言,实际上是玩弄数组下标游戏。因此将回型数组写成下标所表示的形式,如下图所示,其中00的意思是数组下标(0,0),后面的以此类推。

技术分享

当得到上述所示的下标所列出来的图形时,可以发现回型数组主要由的一个轮回刚好是矩阵的四条边,而第一圈的最后一条竖直的边并不与第一圈的开始重合,因此为了方便处理,可以将每条边的“最后一个元素”单独处理,然后画出其主对角线和副对角线,可以得到下图,其中绿色的两条斜线分别为主对角线和副对角线。

技术分享

从图中可以看到:

  • 数字从1~4的过程中,数组下标从00~03;即行下标保持不变,而列下标保持递增
  • 数字从5~8的过程中,数组下标从04~34;即行下标保持递增,而列下标保持不变
  • 数字从9~12的过程中,数组下标从44~41;即行下标保持不变,而列下标保持递减
  • 数字从13~16的过程中,数组下标从40~10;即行下标保持递减,而列下标保持不变

上述过程完成了一个轮回,其他的与上面的步骤相似。对上述步骤分析结合上图,可以得到
水平方向:开始于主对角线,结束于副对角线;
竖直方向:开始于副对角线,结束于主对角线;

对于主对角线上的元素下标满足行下标等于列下标
对于副对角线上的元素行下标与列下标之和等于定常数,而这个定常数恰好为矩阵的维数减1

由此可以得到主对角线元素下标为:(i,i);
副对角线下标为:(i,N-1-i)或(N-1-i,i);

那么再分析下上述的轮回,便可以得到通项表达式:

  • 数字从1~4的过程中,数组下标从(i,i)->(i,N-2-i);
  • 数字从5~8的过程中,数组下标从(i,N-1-i)->(i-1,i);
  • 数字从9~12的过程中,数组下标从(i,i)->(i,N-2-i);
  • 数字从13~16的过程中,数组下标从(N-1-i,i)->(i-1,i);
    注:上述的i只是一种表示方式,不同行列数字变化的过程中,i并不相同。

这里应该注意到该矩阵的维数是奇数还是偶数。如果是奇数,应该注意到最里面的那个数是需要开启新的一轮轮回的,故应特殊对待;而对于偶数,最后一次轮回就可以完成所有的赋值过程。

综上所述,算法的描述如下。

算法描述

void ClipArray(int A[][N]){
    int cnt=0;
    for(int i=0;i<N/2;i++){
        //从左向右
        for(int j=i;j<N-1-i;j++){
            A[i][j]=++cnt;
        }
        //从上向下
        for(int j=i;j<N-1-i;j++){
            A[j][N-1-i]=++cnt;
        }
        //从右向左
        for(int j=N-1-i;j>i;j--){
            A[N-1-i][j]=++cnt;
        }
        //从下向上
        for(int j=N-1-i;j>i;j--){
            A[j][i]=++cnt;
        }
    }
    if(N%2!=0){
        A[N/2][N/2]=++cnt;
    }
}

具体代码见附件。


附件

#include<stdio.h>
#define N 4

void ClipArray(int (*)[N]);
void Show(int (*)[N]);

int main(int argc,char* argv[]){
    int Arry[N][N]={{0}};
    ClipArray(Arry);
    Show(Arry);
    return 0;
}

void ClipArray(int A[][N]){
    int cnt=0;
    for(int i=0;i<N/2;i++){
        //从左向右
        for(int j=i;j<N-1-i;j++){
            A[i][j]=++cnt;
        }
        //从上向下
        for(int j=i;j<N-1-i;j++){
            A[j][N-1-i]=++cnt;
        }
        //从右向左
        for(int j=N-1-i;j>i;j--){
            A[N-1-i][j]=++cnt;
        }
        //从下向上
        for(int j=N-1-i;j>i;j--){
            A[j][i]=++cnt;
        }
    }
    if(N%2!=0){
        A[N/2][N/2]=++cnt;
    }
}

void Show(int A[][N]){
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            printf("%3d",A[i][j]);
            if(j==N-1){
                printf("\n");
            }
        }
    }
}

第3章第1节练习题2 回形矩阵

标签:

原文地址:http://blog.csdn.net/u013595419/article/details/51255155

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!