剑指offer29. 顺时针打印矩阵 P161
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
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
当我们顺时针打印该矩阵时,每一圈的起始位置是左上角的元素,并且每一圈左上角元素都有一个共同点:它的行rows和列cols所对应的的下标都是相同的。因此不难想到,该矩阵打印结束的条件就是左上角的元素下标走到了该矩阵行和列的一半时,该矩阵打印结束了。因为矩阵也是用下标来确定某个数字的,所以这里就是:rows > start * 2 && cols > start * 2
矩阵打印一圈需要四步(从左到右,从上到下,从右到左,从下到上),这个是一般情况,当矩阵是行大于列、列大于行的时候可能不需要四步,就可以打印结束
无论是一个怎样的矩阵,它都会进行第一步从左到右,并且如果打印一个矩阵它进行了第三步,那么一定走了一二步,也就是说后面的每一步是建立在前面步的基础之上的,总结一下打印每一圈:
(1)从左往右:肯定有;
(2)从上到下:矩阵行数至少为2,即:终止行号必须大于起始行号(这里不可以等于,否则会产生矩阵右上角的元素重复多打印一次);
(3)从右往左:矩阵至少为两行两列,即:终止列号必须大于起始列号,并且终止行号必须大于起始行号(同样,不可以等于,否则矩阵右下角的元素会多打印一次);
(4)从下到上:矩阵至少为三行两列,即:终止行号必须比起始行号大2,并且终止列号必须大于起始列号(同样,不可以等于,否则会出现左下角和右上角元素多打印一次)
void print(int **number, int rows, int cols) {
if (number == NULL || rows < 0 || cols < 0) return ;
if (rows == 0 && cols == 0) return;
int start = 0; // 对角线上的行列号
while (rows > start * 2 && cols > start * 2) {
printMatrix(number, rows, cols, start);
++start;
}
}
void printMatrix(int **a, int rows, int cols, int start) { //顺时针打印一圈
int endx = rows - start - 1, endy = cols - start - 1; // 终止行号和列号
for (int i = start; i <= endy; ++i) { // 从左往右,直接打印
cout << a[start][i] << " ";
}
if (endx > start) { // 从上到下:终止行号必须大于起始行号
for (int i = start + 1; i <= endx; ++i) { // 从start+1开始,不然重复打
cout << a[i][endy] << " ";
}
}
if (endx > start && endy > start) { // 从右往左:终止列号必须大于起始列号,并且终止行号必须大于起始行号
for (int i = endy - 1; i >= start; --i) {
cout << a[endx][i] << " ";
}
}
if (endx - 1 > start && endy > start) { //从下到上:终止行号必须比起始行号大2,并且终止列号必须大于起始列号
for (int i = endx - 1; i > start; --i) {
cout << a[i][start] << " ";
}
}
}