1、矩阵的存储及转置算法矩阵的存储及转置算法本文要点:1.对称矩阵与稀疏矩阵2.两种矩阵的压缩存储3.代码实现两种矩阵对称矩阵1.对称矩阵也是一种特殊矩阵,满足Aij = Aji(设矩阵为A,且有0=iN-1 & 0=j=j)3.代码实现cppview plaincopy1. template2. classSymmetryMatrix3. 4. public:5. SymmetryMatrix(constT*a,size_tn)6. :_matrix(newTn*(n+1)/2)7. ,_size(n*(n+1)/2)8. ,_n(n)9. 10. size_tindex=0;/表示一维数组的下
2、标11. for(size_ti=0;in;+i)12. 13. for(size_tj=0;j=j)/存储下三角16. 17. _matrixindex+=ai*n+j;18. /index+;19. 20. else21. continue;22. 23. 24. 25. 26. T&Access(size_trow,size_tcol)/访问数据27. 28. if(rowcol)29. 30. std:swap(row,col);31. 32. return_matrixrow*(row+1)/2+col;33. 34. 35. voidDisplay()36. 37. for(siz
3、e_ti=0;i_n;i+)38. 39. for(size_tj=0;j_n;j+)40. 41. coutAccess(i,j);42. 43. coutendl;44. 45. 46. protected:47. T*_matrix;/压缩存储的一维数组48. size_t_size;/可存储的大小49. size_t_n;/行列的大小50. ;稀疏矩阵1.稀疏矩阵中,有效数据(非0)的数量远小于非法数据的个数(0为非法数据)2.稀疏矩阵的存储也是压缩存储的,但与对称矩阵不同的地方有两点:(1)稀疏矩阵的压缩存储只存储有效值;(2)稀疏矩阵存储以行优先的顺序存储在三元组中,表示为:row
4、,col,value,row和col分别表示该有效值的行和列。一、存储及输出存储的方法类似于对称矩阵的存储,但要将行和列也进行存储;输出的时候多考虑表示数组的下标会不会越界cppview plaincopy1. /数据的存储2. SpareMatrix(constT*a,size_trow,size_tcol,constT&invalid)3. :_rowSize(row)4. ,_colSize(col)5. ,_invalid(invalid)6. 7. for(size_ti=0;irow;i+)8. 9. for(size_tj=0;jcol;j+)10. 11. if(ai*col+
5、j!=invalid)/有效值12. 13. Triplet(i,j,ai*col+j);14. t._value=ai*col+j;15. t._row=i;16. t._col=j;17. _martix.push_back(t);18. 19. 20. 21. 22. /输出23. voidDisplay()24. 25. size_tindex=0;26. for(size_ti=0;i_rowSize;+i)27. 28. for(size_tj=0;j_colSize;+j)29. 30. if(index_martix.size()31. &i=_martixindex._row
6、32. &j=_martixindex._col)33. 34. cout_martixindex._value;35. +index;36. 37. else38. 39. cout0;40. 41. 42. coutendl;43. 44. coutendl;45. 二、一般转置算法从上图我们可以看出:矩阵转置后,三元组中的顺序也发生了改变。因此要得到矩阵M转置后的矩阵TM,我们只需将三元组的顺序改变就好了。转置的三步:a.将矩阵的行列交换b.将每个三元组中的行、列交换c.将原矩阵三元组的顺序重排得到新的三元组cppview plaincopy1. SpareMatrixTransport
7、()/矩阵的转置2. 3. SpareMatrixTSMartix;4. TSMartix._rowSize=_colSize;/交换行列5. TSMartix._colSize=_rowSize;6. TSMartix._invalid=_invalid;7. TSMartix._artix.reserve(_martix.size();8. 9. for(size_tcol=0;col_colSize;+col)/以列优先进行查找10. 11. for(size_tindex=0;index_martix.size();+index)12. 13. if(_martixindex._col
8、=col)14. 15. Tripletmp(_martixindex._col,_martixindex._row,_martixindex._value);16. TSMartix._tix.push_back(tmp);17. 18. 19. 20. returnTSMartix;21. 这样算法即使可以得到结果,但是效率高不高呢?!算算时间复杂度-O(矩阵的列数*有效数值的个数),如果这个矩阵是500*500呢?!显然效率就会特别低了。因此,我们就需要一种转置算法来提高效率。三、快速转置(假设原矩阵为M,转置后得到的矩阵为FSTM)我们按照普通转置的算法,将M的三元组的次序进行转置,并
9、将每次转置后的数据能直接放到FSTM三元组正确的位置。但这种算法的前提是:需要预先知道M每行的有效值个数,将M中第一个有效数放到正确位置后,并记下该位置,以后对M的三元组中的每个数进行转置时,都可以直接放到正确的位置。引入两个量count和start,count-记录每行的有效数据的个数start-表示每行第一个数的起始位置分析上图我们可以得到:start = 上一行的起始位置 + 上一行的有效数个数时间复杂度:O(2*有效值的个数+列数)代码实现:cppview plaincopy1. SpareMatrixFastTransport()2. 3. SpareMatrixFSTMartix;
10、4. FSTMartix._rowSize=_colSize;/交换行列5. FSTMartix._colSize=_rowSize;6. FSTMartix._invalid=_invalid;7. FSTMartix._martix.resize(_martix.size();8. 9. int*count=newint_colSize;10. memset(count,0,_martix.size()*sizeof(int);11. int*start=newint_colSize;12. memset(start,0,_martix.size()*sizeof(int);13. 14.
11、 /统计每列的有效值个数15. for(size_ti=0;i_martix.size();+i)16. 17. count_martixi._col+;18. 19. 20. /计算每一列的起始位置21. for(size_tj=1;j_colSize;+j)22. 23. startj=startj-1+countj-1;/每一列起始位置=上一列起始位置+上一列有效数个数24. 25. 26. /转置27. for(size_tindex=0;index_martix.size();+index)28. 29. size_ttmp=_martixindex._col;/取到原三元组中每个数
12、的列30. FSTMartix._martixstarttmp._col=_martixindex._row;31. FSTMartix._martixstarttmp._row=_martixindex._col;32. FSTMartix._martixstarttmp._value=_martixindex._value;33. +starttmp;/start指针要向后移位34. 35. returnFSTMartix;36. 稀疏矩阵代码的整体实现:cppview plaincopy1. template2. structTriple3. 4. Triple(size_trow,si
13、ze_tcol,constT&value=T()5. :_row(row)6. ,_col(col)7. ,_value(value)8. 9. Triple()10. 11. 12. size_t_row;/行13. size_t_col;/列14. T_value;/有效值15. ;16. 17. template18. classSpareMatrix19. 20. public:21. SpareMatrix()22. :_martix(NULL)23. ,_rowSize(0)24. ,_colSize(0)25. ,_invalid(T()26. 27. /数据的存储28. Spa
14、reMatrix(constT*a,size_trow,size_tcol,constT&invalid)29. :_rowSize(row)30. ,_colSize(col)31. ,_invalid(invalid)32. 33. for(size_ti=0;irow;i+)34. 35. for(size_tj=0;jcol;j+)36. 37. if(ai*col+j!=invalid)/有效值38. 39. Triplet(i,j,ai*col+j);40. t._value=ai*col+j;41. t._row=i;42. t._col=j;43. _martix.push_b
15、ack(t);44. 45. 46. 47. 48. /输出49. voidDisplay()50. 51. size_tindex=0;52. for(size_ti=0;i_rowSize;+i)53. 54. for(size_tj=0;j_colSize;+j)55. 56. if(index_martix.size()57. &i=_martixindex._row58. &j=_martixindex._col)59. 60. cout_martixindex._value;61. +index;62. 63. else64. 65. cout0;66. 67. 68. coute
16、ndl;69. 70. coutendl;71. 72. SpareMatrixTransport()/矩阵的转置73. 74. SpareMatrixTSMartix;75. TSMartix._rowSize=_colSize;/交换行列76. TSMartix._colSize=_rowSize;77. TSMartix._invalid=_invalid;78. TSMartix._martix.reserve(_martix.size();79. 80. for(size_tcol=0;col_colSize;+col)/以列优先进行查找81. 82. for(size_tindex
17、=0;index_martix.size();+index)83. 84. if(_martixindex._col=col)85. 86. Tripletmp(_martixindex._col,_martixindex._row,_martixindex._value);87. TSMartix._martix.push_back(tmp);88. 89. 90. 91. returnTSMartix;92. 93. 94. SpareMatrixFastTransport()95. 96. SpareMatrixFSTMartix;97. FSTMartix._rowSize=_colS
18、ize;/交换行列98. FSTMartix._colSize=_rowSize;99. FSTMartix._invalid=_invalid;100. FSTMartix._martix.resize(_martix.size();101. 102. int*count=newint_colSize;103. memset(count,0,_martix.size()*sizeof(int);104. int*start=newint_colSize;105. memset(start,0,_martix.size()*sizeof(int);106. 107. /统计每列的有效值个数108. for(size_ti=0;i_martix.size();+i)109. 110. count_martixi._col+;111. 112. 113. /计算每一列的起始位置114. for(size_tj=1;j_colSize;+j)115. 116. startj=startj-1+countj-1;/每一列起始位置=上一列起始位置+上一列有效数个数117. 118. 119. /转置120. for(size
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1