顺时针打印矩阵

来源:互联网 发布:js e.target.result 编辑:程序博客网 时间:2024/04/30 23:09

题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如,如果输入如下矩阵:

  1,  2,  3,  4  5,  6,  7,  8  9, 10, 11, 12 13, 14, 15, 16

则依次打印出数字:1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10。

这道题目本身并没有包含什么复杂的数据结构,看似简单,但实际上需要包含多个循环,并还要判断一些边界条件。一步错,步步错。所以我们可以通过画图的形式来将这个问题的思路理清楚。

由于是以从外圈到内圈的顺序依次打印,所以我们可以将这个矩阵看为一圈一圈的。每次打印一圈,然后想办法解决每一圈是如何打印的。

                                                      

先假设我们实现了一个PrinfMatrixInCircle()函数,可以用来打印这个矩阵的任意一圈,那么接下来我们要做的就是循环来调用这个PrinfMatrixInCircle()函数让它从外圈到内圈的打印。那么接下来就有两个问题:

1. 打印的起点:最外圈打印的起点当然是左上角的那个点,坐标为(0,0)。然后下一圈呢?很明显,是(2, 2),在下一圈就是(3, 3)。我们发现了规律,每次打印的起点就是 x 坐标和 y 坐标相等的那个点;

2. 我们可以发现,这个矩阵是6*6的矩阵,它的最内圈的起点坐标为(2, 2),并且,横坐标的2倍小于6,纵坐标的2倍也下于6。接下来,再把内部浅色的矩阵想象为一个单独的矩阵,它是4*4的,它最内圈的起点是(1, 1),并且横坐标的2倍小于4,纵坐标的2倍也小于4。再比如,某个矩阵只有一个点,1*1矩阵,它最内圈的起点是(0, 0),并且横坐标的2倍小于1,纵坐标的2倍也小于1。假设这个起点坐标为(start,start),所以我们就发现,循环继续的条件是start*2<rows,start*2<cols。并且这个结论适用于其它的矩阵,你可以自己试试。

于是我们可以写出这样的函数:

void PrintMatrixClockwisly(int (*arr)[COLS], int rows, int cols){int start = 0;assert(NULL != arr);if (0 >= rows || 0 >= cols){return;}while (rows > start * 2 && cols > start * 2){PrintMatrixInCircle(arr, rows, cols, start);++start;}printf("\n");}

接下来就是要实现PrinfMatrixInCircle()打印一圈这个函数:

还是从上边这张图来看:对于这个矩阵,我们可以把打印一圈分为四步:1. 从左至右打印一行;2. 从上到下打印一列;3. 从右至左打印一行; 4。 从下至上打印一列。并且在其中的每一步中,我们可以根据终点坐标和起点坐标打印这一行或者一列。但需要小心点是,不是所有的矩阵都每圈都要经历这四步。比如:

                                                      

比如上面这三个矩阵,它们的最内圈分别只需要三步、两步、一步。

因此我们打印需要判断他的条件。第一步肯定是需要的,因为打印一圈至少要有第一行。如果只有一行,就不用第二步了,也就是说打印第二步的条件是它的终止行号大于其实行号。再来看第三步,至少也要两行两类才行吧,也就是说进行第三步的条件是终止列号大于其实列号,终止行号大于起始行号。再来看第四步,至少也要有三行两列才可以,也就是说它的条件终止列号大于其实列号,终止行号比其实行号至少大2.

如此一来,我们可以按着思路来写这个函数了:

void PrintMatrixInCircle(int (*arr)[COLS], int rows, int cols, int start){int end_x = cols - 1 - start;int end_y = rows - 1 - start;int i = 0;for (i = start; i <= end_x; i++)//从左至右打印一行{printf("%d ", arr[start][i]);}if (end_y > start)//从上到下打印一列{for (i = start + 1; i <= end_y; i++){printf("%d ", arr[i][end_x]);}}if (end_x > start && end_y > start)//从右至左打印一行{for (i = end_x - 1; i >= start; i--){printf("%d ", arr[end_y][i]);}}if (end_x > start && end_y > start + 1)//从下至上打印一列{for (i = end_y - 1; i > start; i--){printf("%d ", arr[i][start]);}}}

对于这种只凭头脑难以想象的题目,画图分析可真是一个好方法!

最后,记得测试呦!

1 0
原创粉丝点击