您的位置:首页 > 编程语言 > C语言/C++

【重构】人人都来写算法 之 矩阵顺时针旋转90度,空间效率O(1),时间效率O(n*n)

2014-03-11 17:54 477 查看
中午抽了15分钟空闲时间对之前的一段代码进行了重构,虽然使用指针操作二维数组在可读性上没有原来的二维下标访问清晰,但是为了消除重复也只能这样了。

原文链接:

http://blog.csdn.net/walle_love_eva/article/details/9951977

之前的代码之所以存在重复代码的坏味道,主要是我希望测试奇数方阵和偶数方阵两种情况,最初函数是传入二维数组的下标引用,但是第二维下标必须明确,因此导致重复代码。

但是,我们假设,我们是在一个固定大小图像上截取一个奇数方阵或者偶数方阵来进行测试,因此也就可以解决这个问题。

此外需要特别说明的一点是,正如前一篇文章所言,两种不同的方法都可以解决,同时两种方法我又进行了细微的变通,因此四个不同的算法函数可以实现这一转换。因此我分别调用这四个函数,让一个矩阵进行4四顺时针90度的转换,又变回原图像,以此对算法进行验证。只要其中任何一个算法出现问题,4次转换后矩阵就和原来的不同。

第一次重构后的代码:

#include <iostream>
#include <iomanip>

using std::cout;
using std::endl;
using std::setw;

const int SIZE_4 = 4;
const int SIZE_7 = 7;

void printImage(int* matrix, int size)
{
for(int i=0; i<size; ++i)
{
for(int j=0; j<size; ++j)
{
cout<<setw(4)<<matrix[i*size + j]<<" ";
}
cout<<endl;
}
cout<<"-----------------------------"<<endl;
}

void swap(int &a, int &b)
{
if(&a == &b)
{
return;
}
int temp = a;
a = b;
b = temp;
}

void swap_bitOpt(int &a, int &b)
{
if(&a == &b)
{
return;
}
a = a^b;
b = a^b;
a = a^b;
}

void transpose90_zero(int* matrix, int size)
{
//Diagonal Flip
for(int i=0; i<size; ++i)
{
for(int j=i+1; j< size; ++j)
{
swap_bitOpt(matrix[i*size + j], matrix[j*size + i]);
}
}

//Flip form left to right
for(int i=0; i<size; ++i)
{
for(int j=0; j<size/2; j++)
{
swap(matrix[i*size +j], matrix[i*size +(size-j-1)]);
}
}
}

void transpose90_one(int* matrix, int size)
{
//Flip up and down
for(int i=0; i<size/2; ++i)
{
for(int j=0; j<size; j++)
{
swap(matrix[i*size +j], matrix[(size-i-1)*size +j]);
}
}

//Diagonal Flip
for(int i=0; i<size; ++i)
{
for(int j=i+1; j< size; ++j)
{
swap(matrix[i*size + j], matrix[j*size + i]);
}
}
}

void transpose90_two(int* matrix, int size)
{
for(int layer=0; layer<size/2; ++layer)
{
int first = layer;
int last = size-1-layer;

for(int i=first; i<last; ++i)
{
int offset = i - first;
int top = matrix[first*size + i];
matrix[first*size + i] = matrix[(last-offset)*size + first];
matrix[(last-offset)*size + first] = matrix[last*size +(last-offset)];
matrix[last*size + (last-offset)] = matrix[i*size + last];
matrix[i*size + last] = top;
}
}
}

void transpose90_three(int* matrix, int size)
{
for(int layer=0; layer<size/2; ++layer)
{
int last = size-layer -1;
int iter = 0;
for(int i=layer; i<last; ++i)
{
int reverse_i = last - iter;
int top = matrix[layer*size + i];
matrix[layer*size + i] = matrix[reverse_i*size + layer];
matrix[reverse_i*size + layer] = matrix[last*size + reverse_i];
matrix[last*size + reverse_i] = matrix[i*size + last];
matrix[i*size + last] = top;
iter++;
}
}
}

int main()
{
int image[SIZE_7][SIZE_7] = {
{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,26,27,28},
{29,30,31,32,33,34,35},
{36,37,38,39,40,41,42},
{43,44,45,46,47,48,49}};

//Test even matrix
printImage((int*)image, 4);
transpose90_zero((int*)image, 4);
printImage((int*)image, 4);
transpose90_one((int*)image, 4);
printImage((int*)image, 4);
transpose90_two((int*)image, 4);
printImage((int*)image, 4);
transpose90_three((int*)image, 4);
printImage((int*)image, 4);

//Test odd matrix
printImage((int*)image, 7);
transpose90_zero((int*)image, 7);
printImage((int*)image, 7);
transpose90_one((int*)image, 7);
printImage((int*)image, 7);
transpose90_two((int*)image, 7);
printImage((int*)image, 7);
transpose90_three((int*)image, 7);
printImage((int*)image, 7);

getchar();
}

现在再看这段代码,可读性比最初确实大打折扣,二维数组下标访问变成了一维数组下标访问。我觉得还是需要继续重构,或者改善代码的可读性。

在继续重构前,我再次明确下最初的想法:我希望的是旋转一副位图图像,假设位图图像大小是一定的,我仅仅需要在main函数中测试偶数矩阵和奇数矩阵的转换,那么我怎么传入更加合适呢?

第二次重构的代码如下:

#include <iostream>
#include <iomanip>

using std::cout;
using std::endl;
using std::setw;

const int SIZE_MATRIX = 100;

void printImage(int matrix[][SIZE_MATRIX], int size)
{
for(int i=0; i<size; ++i)
{
for(int j=0; j<size; ++j)
{
cout<<setw(4)<<matrix[i][j]<<" ";
}
cout<<endl;
}
cout<<"-----------------------------"<<endl;
}

void swap(int &a, int &b)
{
if(&a == &b)
{
return;
}
int temp = a;
a = b;
b = temp;
}

void transpose90_zero(int matrix[][SIZE_MATRIX], int size)
{
//Diagonal Flip
for(int i=0; i<size; ++i)
{
for(int j=i+1; j< size; ++j)
{
swap(matrix[i][j], matrix[j][i]);
}
}

//Flip form left to right
for(int i=0; i<size; ++i)
{
for(int j=0; j<size/2; j++)
{
swap(matrix[i][j], matrix[i][size-j-1]);
}
}
}

void transpose90_one(int matrix[][SIZE_MATRIX], int size)
{
//Flip up and down
for(int i=0; i<size/2; ++i)
{
for(int j=0; j<size; j++)
{
swap(matrix[i][j], matrix[size-i-1][j]);
}
}

//Diagonal Flip
for(int i=0; i<size; ++i)
{
for(int j=i+1; j< size; ++j)
{
swap(matrix[i][j], matrix[j][i]);
}
}
}

void transpose90_two(int matrix[][SIZE_MATRIX], int size)
{
for(int layer=0; layer<size/2; ++layer)
{
int first = layer;
int last = size-1-layer;

for(int i=first; i<last; ++i)
{
int offset = i - first;
int top = matrix[first][i];
matrix[first][i] = matrix[last-offset][first];
matrix[last-offset][first] = matrix[last][last-offset];
matrix[last][last-offset] = matrix[i][last];
matrix[i][last] = top;
}
}
}

void transpose90_three(int matrix[][SIZE_MATRIX], int size)
{
for(int layer=0; layer<size/2; ++layer)
{
int last = size-layer -1;
int iter = 0;
for(int i=layer; i<last; ++i)
{
int reverse_i = last - iter;
int top = matrix[layer][i];
matrix[layer][i] = matrix[reverse_i][layer];
matrix[reverse_i][layer] = matrix[last][reverse_i];
matrix[last][reverse_i] = matrix[i][last];
matrix[i][last] = top;
iter++;
}
}
}

int main()
{
int image[SIZE_MATRIX][SIZE_MATRIX] = {
{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,26,27,28},
{29,30,31,32,33,34,35},
{36,37,38,39,40,41,42},
{43,44,45,46,47,48,49}};

//Test even matrix
printImage(image, 4);
transpose90_zero(image, 4);
printImage(image, 4);
transpose90_one(image, 4);
printImage(image, 4);
transpose90_two(image, 4);
printImage(image, 4);
transpose90_three(image, 4);
printImage(image, 4);

//Test odd matrix
printImage(image, 7);
transpose90_zero(image, 7);
printImage(image, 7);
transpose90_one(image, 7);
printImage(image, 7);
transpose90_two(image, 7);
printImage(image, 7);
transpose90_three(image, 7);
printImage(image, 7);

getchar();
}


新的重构中,果断删除通过位运算来进行交换的函数,因为在性能差别不大的情况下,谁会喜欢更加难懂的代码呢?

很多时候,一段代码仅仅细微的改变就可以大大改善程序的可读性,那为什么我们不多做一些工作,将代码写的更好呢?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ 二维数组 重构
相关文章推荐