題目:輸入一個矩陣,rows行,columns列,按順時針方向從外向裏一次打印每一個數字。
分析:首先整體分析循環:第一個環的起點是(0,0),第二個環的起點是(1,1)……,依次得出每個環的起點都是行號和列號相等的點,表示爲(start,start)。如果一個環的起點start<rows/2 && start<columns/2,那麼就可以繼續循環;
然後具體分析每個環的打印情況:對每個環,總是要執行從左到右的打印;如果起點start小於該環的行終結號,則需要打印從上到下的列;如果起點start小於該環的行終結號,並且起點start小於該環的列終結號,則需要打印從右向左的行;如果起點start該環的列終結號,並且小於該環的行終結號-1,則需要打印從下向上的列。
下面是具體代碼實現:
#include <iostream>
using namespace std;
void Circle(int **data,int rows,int columns);
void PrintMatrix(int **data,int rows,int columns,int start);
int main()
{
int data[4][4]={
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,16}
};
Circle((int **)data,4,4);
cout <<endl;
return 0;
}
//整體規劃打印環的執行
void Circle(int **data,int rows,int columns)
{
if (data==NULL || rows<=0 || columns<=0)
return;
int start=0;
while(rows > start*2 && columns > start*2)
{
PrintMatrix((int **)data,rows,columns,start);
start++;
}
}
//具體分析每個環內的打印次序
void PrintMatrix(int **data,int rows,int columns,int start)
{
//只定義一個起點start是因爲每個環的起點都是(start,start)
int endx=columns-1-start;
int endy=rows-1-start;
//從左到右打印該環的第一行
for (int i=start;i<=endx;i++)
{
//cout <<data[start][i] <<" ";
//cout <<*(data+start*columns+i) <<" ";
printf("%d ",*(data+start*columns+i));
/*二維指針做形參,不能以二維數組的形式輸出,所以第一種方式cout <<data[start][i] 是錯誤的,
更不能以一維數組data[start*columns+i]的形式輸出;
二維指針默認的是地址的地址,所以第二種方式cout <<*(data+start*columns+i)取一個*結果爲16進制的形式;
因此,只能通過printf,用%d強制將16進制轉換爲10進制*/
}
//判斷是否需要從上到下打印該列,需要打印的條件是該環的行數大於起點的行號
if (endy > start)
{
for (i=start+1;i<=endy;i++)
{
//cout <<data[i][endx] <<" ";
//cout <<*(data+i*columns+endx) <<" ";
printf("%d ",*(data+i*columns+endx));
}
}
//判斷是否需要從右到左打印該行,需要打印的條件是該環的列數大於起點的列號,行數大於起點的行號
if (endx > start && endy > start)
{
for (i=endx-1;i>=start;i--)
{
//cout<<data[endy][i] <<" ";
//cout <<*(data+endy*columns+i) <<" ";
printf("%d ",*(data+endy*columns+i));
}
}
//判斷是否需要從下到上打印該行,需要打印的條件是該環的列數大於起點的列號,行數大於起點的行號-1
if (endy-1 > start && endx > start)
{
for (i=endy-1;i>start;i--)
{
//cout <<data[i][start] <<" ";
//cout <<*(data+i*columns+start) <<" ";
printf("%d ",*(data+i*columns+start));
}
}
}