顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
例如:如果输入如下矩阵:
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。
思路:
1.首先判断一次顺时针打印是否符合条件:由于每一次打印的起始坐标为(start,start),start从0开始,即(0,0),打印一次加1,经过推算得出顺时针打印条件为(列数>2*start && 行数>2*start)
2.然后开始一次顺时针打印,分4个步骤组成:(除了第一个步骤,每个步骤都不是必须进行的,需要满足一定条件)
(1). 从左到右打印,只要符合顺时针打印的条件就必须进行第一步
(2). 从上到下打印,条件是列数至少含有2列
(3).从右向左打印,条件是至少包含两行两列
(4). 从下到上打印,条件是至少包含两行三列
实现代码如下:
#include<iostream> using namespace std; //执行一次顺时针打印的函数,需要四个步骤,但每一步都不是必须的,有可能只需要几步 void subprint(int **data,int rows,int columns,int start) { int endx=columns-1-start; int endy=rows-1-start; //第一步,从左到右打印,这一步必须执行 for(int i=start;i<=endx;i++) { int number=data[start][i]; cout<<" "<<number; } //第二步,从上到下打印,条件是至少包含两行 for(int i=start+1;i<=endy;i++) { cout<<" "<<data[i][endx]; } //第三步,从右向左打印,条件是至少包含两行两列 for(int i=endx-1;i>=start;--i) { cout<<" "<<data[endy][i]; } //第四步,从下到上打印,条件是至少包含两行三列 for(int i=endy-1;i>=start+1;--i) { cout<<" "<<data[i][start]; } } //函数实现 void print(int **data,int rows,int columns) { try { if(data==NULL||rows<=0||columns<=0) throw new exception("参数错误!"); int start=0; //一次顺时针打印的条件是rows>2*start && columns>2*start while(rows>2*start && columns>2*start) { subprint(data,rows,columns,start); start++; } } catch(exception e) { cerr<<e.what()<<endl; } }
这里注意一下我定义的函数的形参为二级指针,而实参不可以直接是二维数组,必须初始化为指针数组(实际是一个数组,数组中每一个元素是一个指针)
如果非要二维数组作为实参的话,形参必须为指向数组的指针(数组指针)
测试代码及运行结果:
int main() { int data[4][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; int *p[4];//指针数组,实际是一个数组,数组中每一个元素是一个指针 //给指针数组赋值 for(int i=0;i<4;i++) { p[i]=data[i]; } print(p,4,4); return 0; }
简单解释一下指针数组和数组指针的区别:
由于指针数组中的每一个元素都为一个指针,而data[i]代表第i个分数组的首地址,故可以p[i]=data[i]可以完成指针数组的初始化;
而数组指针代表的是指向一个数组的指针,它的初始化如下(和本例无关)
//数组指针,实际是指向数组的指针,是一个指针 int (*p2)[4];//p2是指向 有4个元素的数组 的指针 //数组指针的初始化 p2=data;//data为0行分数组的地址,将他赋值给p2指针,并且data==&data[0]成立,将&data[0]赋值给p2也是一样的 p2=&data[0];