内容:
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每个数字。例如下列矩阵:
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
解题思路:
设行数为row,列数col,打印第一圈的左上角坐标为(0,0),第二圈左上角坐标为(1,1),以此类推左上角行列相等,所以选取左上角为(start,start)。对5*5来说,最后一圈只有一个数字,对应的坐标为(2,2),对于6*6来说,最后一圈4个数字,对应左上角坐标为(2,2)。我们发现6>2*2,所以推出循环条件为col>startX*2,且row>startY*2。
用下面循环来打印:
void printclockwise(int a[][4], int row, int col)
{
assert(a);
int start = 0;
while (row > start * 2 && col > start * 2){
printcircle(a, row, col, start);
start++;
}
}
然后打印一圈,分四步:第一步从左到右打印,第二部从下到上打印,第三部从右往左打印,第四步从下到上打印。第一步总是需要的,因为打印一圈至少有一步,如果只有一行则不需要第二步。也就是需要第二步的条件是终止行号大于起始行号。需要第三步打印的前提是圈内至少有两行两列,也就是说除了终止行号大于起始行号,终止列号大于起始列号。需要打印第四步则最少需要三行两列,因此终止行要比起始行至少大2,同时终止列大于其实列。
void printcircle(int a[][4],int row,int col,int start)
{
int endY = col - 1 - start; //列数
int endX = row - 1 - start; //行数
//从左到右打印行
for (int i = start; i <=endY; i++){
print(a[start][i]);
}
//从上到下打印列
if (start < endX){
for (int i = start + 1; i <= endX; i++){
print(a[i][endY]);
}
}
//从右向左打印行
if (start < endY&&start < endX){
for (int i = endY-1; i >= start; i--){
print(a[endX][i]);
}
}
//从下到上打印列
if ((start < endY)&&(start < endX-1)){
for (int i = endX - 1; i >= start+1; i--){
print(a[i][start]);
}
}
}
void print(int n)
{
printf("%d ", n);
}