Author: Frank
描述:编写一个函数,输入一个矩阵,按照从外向里以顺时针的顺序一次打印出每一个数字。
(用状态转换的方法应该也可以,定义参数标致当前的前进方向,右,下,左,上, 定义二维数组标记被访问过的元素, 当向右到尽头时,转向下..)
例如输入的矩阵为:
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.
分析:(key:二维数组做入参,按照圈数打印)
将矩阵中的数字按照圈输出,1 2 3 4 8 12 16 15 14 13 9 5为第一圈;6 7 11 10为第二圈。
首先,需要确定圈数,设矩阵的行数为row, 列数为column,则圈数取决于两者中的小者。令min = (row >= column) ? column : row; 如果min为偶数,则圈数为min/2;如果min为奇数,则圈数为(min-1)/2, 另外还剩余一行或一列元素需要单独输出。当min==row时,各个圈都输出后,最后需要单独输出剩余的那一行的数据;当min==column时,各个圈都输出后,最后需要单独输出剩余的那一列的数据;
其次,需要设计如何输出一圈的数据。
如上图所示,将一圈的数据分成四个部分,每个部分用一个for循环即可输出,每个部分的起止下标与当前是第几圈有关。假设数组A的行数为row,列数为column:
第0圈: 第一部分 A[0][0~column-2];第二部分 A[0~row-2][column-1];第三部分A[row-1][column-1~1];第四部分A[row-1~1][0]
第1圈: 第一部分 A[1][1~column-3];第二部分 A[1~row-3][column-2];第三部分A[row-2][column-2~2];第四部分A[row-2~2][1]
........
第i圈: 第一部分 A[i][i~column-2-i];第二部分 A[i~row-2-i][column-1-i];第三部分A[row-1-i][column-1-i~i+1];第四部分A[row-1-i~i][i]
代码:
void printUpRow(int* A, int row, int column, int ciecleIdx)
{
for (int i = ciecleIdx; i<= column-2-ciecleIdx;i++)
printf("%d ", *((int*)A + column * ciecleIdx + i));//A[ciecleIdx][i]
}
void printRightColumn(int* A, int row, int column, int ciecleIdx)
{
for (int i = ciecleIdx; i <= row - 2 - ciecleIdx; i++)
printf("%d ", *((int*)A + column * i + (column - 1 - ciecleIdx)));//A[i][column-1-ciecleIdx]
}
void printBottomRow(int* A, int row, int column, int ciecleIdx)
{
for (int i = column-1-ciecleIdx; i >= ciecleIdx+1; i--)
printf("%d ", *((int*)A + column * (row - 1 - ciecleIdx) + i));//A[row - 1 - ciecleIdx][i]
}
void printLeftColumn(int* A, int row, int column, int ciecleIdx)
{
for (int i = row - 1 - ciecleIdx; i >= ciecleIdx + 1; i--)
printf("%d ", *((int*)A + column *i + ciecleIdx));//A[i][ciecleIdx]
}
void PrintMatrixClockwise(int* A, int row, int column)
{
if (row < 1 || column < 1)
return;
int circleNum = 0;
bool extra = false;
int min = (row >= column) ? column : row;
if (0 == min % 2)
{
circleNum = min / 2;
}
else
{
circleNum = (min-1) / 2;
extra = true;//最后需要单独输出剩余的行或列
}
for (int circleIdx = 0; circleIdx < circleNum; circleIdx++)
{
//print one row
printUpRow(A, row, column, circleIdx);
//print one column
printRightColumn(A, row, column, circleIdx);
//print one row
printBottomRow(A, row, column, circleIdx);
//print one column
printLeftColumn(A, row, column, circleIdx);
}
if ((extra == true))//最后需要单独输出剩余的行或列
{
//print the left row or column
if (row >= column)
{
int leftColumIdx = (column - 1) / 2;
for (int i = circleNum; i <= row - 1 - circleNum; i++)
printf("%d ", *((int*)A + column *i + leftColumIdx));//A[i][leftColumIdx]
}
else
{
int leftRowIdx = (row - 1) / 2;
for (int i = circleNum; i <= column - 1 - circleNum; i++)
printf("%d ", *((int*)A + column *leftRowIdx + i));//A[leftRowIdx][i]
}
}
printf("\n------------------------------------------\n");
}
测试代码:
int main()
{
int A[3][5] = { {1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};
PrintMatrixClockwise((int*)A, 3, 5);
int A1[1][5] = { { 1,2,3,4,5 } };
PrintMatrixClockwise((int*)A1, 1, 5);
int A2[5][1] = { 1,2,3,4,5 };
PrintMatrixClockwise((int*)A1, 5, 1);
int A3[5][3] = { {1,2,3},{4,5,6},{7,8,9},{10,11,12},{13,14,15} };
PrintMatrixClockwise((int*)A3, 5, 3);
int A4[5][5] = { { 1,2,3,4,5 },{ 6,7,8,9,10 },{11,12,13,14,15 },{16,17,18,19,20},{ 21,22,23,24,25 } };
PrintMatrixClockwise((int*)A4, 5, 5);
int A5[1][1] = { 1 };
PrintMatrixClockwise((int*)A1, 1, 1);
getchar();
return 0;
}
用状态转换的方法应该也可以,定义参数标致当前的前进方向,右,下,左,上, 定义二维数组标记被访问过的元素, 当向右到尽头时,转向下..
enum class DIR {
Right = 0,
Down,
Left,
Up
};
bool getNextLocation( vector<vector<char>>& markArr, int rowNum, int colNum,
DIR& currDir,
int lastRowIdx, int lastColuIdx,
int& nextRowIdx, int& nextColuIdx) {
if (currDir == DIR::Right) {
if (lastColuIdx + 1 < colNum && markArr[lastRowIdx][lastColuIdx + 1] == 0) {
nextRowIdx = lastRowIdx;
nextColuIdx = nextColuIdx + 1;
markArr[nextRowIdx][nextColuIdx] = 1;
return true;
}
else {
if (markArr[lastRowIdx + 1][lastColuIdx] == 0 && lastRowIdx + 1< rowNum) {
nextRowIdx = lastRowIdx+1;
nextColuIdx = lastColuIdx;
markArr[nextRowIdx][nextColuIdx] = 1;
currDir = DIR::Down;
return true;
}
}
}
else if (currDir == DIR::Down) {
if (lastRowIdx + 1 < rowNum && markArr[lastRowIdx+1][lastColuIdx] == 0) {
nextRowIdx = lastRowIdx+1;
nextColuIdx = nextColuIdx;
markArr[nextRowIdx][nextColuIdx] = 1;
return true;
}
else {
if (markArr[lastRowIdx][lastColuIdx-1] == 0 && lastColuIdx -1>= 0) {
nextRowIdx = lastRowIdx;
nextColuIdx = lastColuIdx-1;
markArr[nextRowIdx][nextColuIdx] = 1;
currDir = DIR::Left;
return true;
}
}
}
else if (currDir == DIR::Left) {
if (lastColuIdx -1 >= 0 && markArr[lastRowIdx][lastColuIdx - 1] == 0) {
nextRowIdx = lastRowIdx;
nextColuIdx = lastColuIdx - 1;
markArr[nextRowIdx][nextColuIdx] = 1;
return true;
}
else {
if (markArr[lastRowIdx - 1][lastColuIdx] == 0 && lastRowIdx - 1 >= 0) {
nextRowIdx = lastRowIdx- 1;
nextColuIdx = lastColuIdx;
markArr[nextRowIdx][nextColuIdx] = 1;
currDir = DIR::Up;
return true;
}
}
}
else if(currDir == DIR::Up) {
if (lastRowIdx - 1 >=0 && markArr[lastRowIdx - 1][lastColuIdx] == 0) {
nextRowIdx = lastRowIdx - 1;
nextColuIdx = nextColuIdx;
markArr[nextRowIdx][nextColuIdx] = 1;
return true;
}
else {
if (markArr[lastRowIdx][lastColuIdx + 1] == 0 && lastColuIdx + 1 < colNum) {
nextRowIdx = lastRowIdx;
nextColuIdx = lastColuIdx + 1;
markArr[nextRowIdx][nextColuIdx] = 1;
currDir = DIR::Right;
return true;
}
}
}
return false;
}
void printArry(vector<vector<int>> arr, int rowNum, int colNum) {
if (arr.size() < 0) {
return;
}
vector<vector<char>> markArr(rowNum, vector<char>(colNum,0));//标记元素是否已经被访问过
int lastRowIdx = 0;
int lastColIdx = 0;
cout << arr[0][0];//输出第一个元素
markArr[0][0] = 1;
int nextRowIdx = 0;
int nextColuIdx = 0;
DIR currDir = DIR::Right;
while (getNextLocation(markArr, rowNum, colNum, currDir, lastRowIdx, lastColIdx, nextRowIdx, nextColuIdx)) {
cout << arr[nextRowIdx][nextColuIdx];
lastRowIdx = nextRowIdx;
lastColIdx = nextColuIdx;
}
}
int main() {
vector<vector<int>> arr(3, vector<int>(3, 0));
arr[0][0] = 1; arr[0][1] = 2; arr[0][2] = 3;
arr[1][0] = 4; arr[1][1] = 5; arr[1][2] = 6;
arr[2][0] = 7; arr[2][1] = 8; arr[2][2] = 9;
printArry(arr,3,3);
return 1;
}