【重构】人人都来写算法 之 矩阵顺时针旋转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次转换后矩阵就和原来的不同。
第一次重构后的代码:
现在再看这段代码,可读性比最初确实大打折扣,二维数组下标访问变成了一维数组下标访问。我觉得还是需要继续重构,或者改善代码的可读性。
在继续重构前,我再次明确下最初的想法:我希望的是旋转一副位图图像,假设位图图像大小是一定的,我仅仅需要在main函数中测试偶数矩阵和奇数矩阵的转换,那么我怎么传入更加合适呢?
第二次重构的代码如下:
新的重构中,果断删除通过位运算来进行交换的函数,因为在性能差别不大的情况下,谁会喜欢更加难懂的代码呢?
很多时候,一段代码仅仅细微的改变就可以大大改善程序的可读性,那为什么我们不多做一些工作,将代码写的更好呢?
原文链接:
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(); }
新的重构中,果断删除通过位运算来进行交换的函数,因为在性能差别不大的情况下,谁会喜欢更加难懂的代码呢?
很多时候,一段代码仅仅细微的改变就可以大大改善程序的可读性,那为什么我们不多做一些工作,将代码写的更好呢?
相关文章推荐
- 人人都来写算法 之 矩阵顺时针旋转90度,空间效率O(1),时间效率O(n*n)
- 有一副由NxN矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存空间的情况下(即不使用缓存矩阵),将图像顺时针旋转90度。 给定一个NxN的矩阵,和矩阵的阶数N,请返回旋转
- 有一副由NxN矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存空间的情况下(即不使用缓存矩阵),将图像顺时针旋转90度。
- JAVA代码—算法基础:将N*N的矩阵顺时针旋转90度输出元素
- leecode 矩阵顺时针旋转90度
- 算法-将矩阵逆时针旋转90度
- 【数据结构】排序算法时间效率、空间效率以及算法稳定性总结
- 顺时针旋转图片90度(算法)
- 矩阵顺时针旋转90度
- M*N矩阵顺时针旋转90度
- 将n*n矩阵顺时针旋转90度
- 算法题:矩阵旋转90度
- Arithmetic problem | 在原地顺时针90度旋转矩阵图像
- 数据结构-算法效率的度量-时间复杂度和空间复杂度
- 把矩阵顺时针旋转90度
- Java实现矩阵顺时针旋转90度
- 数组字符串系列之,将矩阵逆时针旋转90度,要求使用最少的额外空间
- 一张图像表示成NxN的矩阵,图像中每个像素是4个字节,写一个函数把图像旋转90度。 你能原地进行操作吗?(即不开辟额外的存储空间)
- 矩阵顺时针旋转90度
- 使用一个额外变量解决”请用最少的额外空间将一个M*N的矩阵旋转90度“