“《编程珠玑》(第2版)第2章”:课后习题7(矩阵转置)
课后习题7是这样子的:
在20世纪60年代早期,Vic Vyssotsky与一个程序员一起工作,该程序员需要转置一个存储在磁带上的4000*4000的矩阵(每条记录的格式相同,为数十个字节)。他的同事最初提出的程序需要运行50个小时。Vyssotsky如何将运行时间减少到半个小时呢?
课后给出的答案是:
为每条记录插入列号和行号,然后调用系统的磁带排序程序先按列排序再按行排序,最后使用另一个程序删除列号和行号。
先对所有数据按列排序,能够将原属于同一列但在不连续内存上的数据,搬移到同一行且内存连续的内存块(一行);
接下来,对每一行进行排序,将每行的数据按序排列好。
程序代码如下:
1 #include <iostream> 2 #include <iomanip> 3 #include <stdlib.h> 4 using namespace std; 5 6 typedef struct 7 { 8 int row; 9 int col; 10 int value; 11 }Data; 12 13 int compareByCol(const void * a, const void * b) 14 { 15 return ((Data*)a)->col - ((Data*)b)->col; 16 } 17 18 int compareByRow(const void * a, const void * b) 19 { 20 return ((Data*)a)->row - ((Data*)b)->row; 21 } 22 23 int main() 24 { 25 const int ROW = 10; 26 const int COL = 10; 27 const int LEN = ROW * COL; 28 int matrix[ROW][COL]; 29 Data data[LEN]; 30 31 cout << "Original matrix: " << endl; 32 for (int i = 0; i < ROW; i++) 33 { 34 for (int j = 0; j < COL; j++) 35 { 36 matrix[i][j] = i * ROW + j + 1; 37 cout << setw(5) << matrix[i][j] << " "; 38 } 39 cout << endl; 40 } 41 cout << endl; 42 43 // Add row and column to each data in matrix 44 for (int i = 0; i < ROW; i++) 45 { 46 for (int j = 0; j < COL; j++) 47 { 48 data[i * ROW + j].row = i; 49 data[i * ROW + j].col = j; 50 data[i * ROW + j].value = matrix[i][j]; 51 } 52 } 53 54 // Sort the whole 'data' in ascending order by column 55 qsort(data, LEN, sizeof(Data), compareByCol); 56 57 // Sort each fragment of ROW length in ascending order by row 58 for (int i = 0; i < ROW; i++) 59 { 60 qsort(&data[i * ROW], ROW, sizeof(Data), compareByRow); 61 } 62 63 // Remove row and column for each data in matrix 64 for (int i = 0; i < ROW; i++) 65 { 66 for (int j = 0; j < COL; j++) 67 { 68 matrix[i][j] = data[i * ROW + j].value; 69 } 70 } 71 72 cout << "Original matrix transposed: " << endl; 73 for (int i = 0; i < ROW; i++) 74 { 75 for (int j = 0; j < COL; j++) 76 { 77 cout << setw(5) << matrix[i][j] << " "; 78 } 79 cout << endl; 80 } 81 cout << endl; 82 83 return 0; 84 }
程序运行结果如下: