What is a symmetric matrix (Symmetricmatrix)?
Symmetrical symmetry-------See
Set a n*n square a,a any element Aij, when and only if Aij = = Aji(0 <= i <= N-1 && 0 <= J <= N-1), then matrix A is a symmetric matrix. Separated by the diagonal of the matrix, it is divided into upper and lower triangles.
Compressed storage is the matrix storage only need to store the upper triangle/lower triangle of data, so the maximum number of N (n+1)/2 data.
the correspondence between symmetric matrices and compressed storage: Lower triangle storage i>=j, S YMMETRICM Atrix [i][j] = = array[i* (i+1)/2+j]
650) this.width=650; "src=" Http://s1.51cto.com/wyfs02/M01/7F/23/wKiom1cUrRbTJ4_iAAAIZYb5ioo408.png "title=" 40%y7~ Z1ngd4muubk2q_lge.png "alt=" Wkiom1currbtj4_iaaaizyb5ioo408.png "/>
So, how do we store it?
Template<class t>class symmetricmatrix{public:symmetricmatrix (T* a, size_t size , size_t n): _data (new t[n* (n + 1) / 2]) // Open up an array of half-size space, _size (size), _n (n) {size_t index = 0;for (size_t i = 0; i < _n; i++) {for (size_t j = 0; j < _n; j++) {if (i >= j) //triangle element {_data[index++] = a[i*n + j];} Else{break;}}}} Public:void display () {size_t index = 0;for (size_t i = 0; i < _n; i++) {for (size_t j = 0; j < _n; j++) {if (i &NBSP;>=&NBSP;J) {cout << _data[i* (i + 1) / 2 + j]<< " ";} else //Upper triangle position {cout << _data[j* (j + 1) / 2 + i]<< " "; //exchange column coordinate}}cout << endl;} Cout << endl;} Gets a row of a column element t& access (size_t i, size_t j) {if (i < j) {swap (i, j);} return _data[i* (i + 1) / 2 + j];} protected:t* _data;size_t _size;size_t _n;};
What is sparse matrix?
compressed storage values store a very small number of valid data. Using {row,col,value} ternary group to store each valid data, ternary group according to the position in the original matrix, in order to store the priority of the row in succession.
First build triples (each of these triples is an element in the matrix)
Template<class t>struct triple{t _value;size_t _col;size_t _row; Triple (const t& value = T (), size_t row = 0, size_t col = 0): _value (value), _row (Row), _col (col) {}};
The valid values are stored again.
Create a class, in which we implement the storage of valid values in the constructor
Sparsematrix (t* A, size_t m, size_t N, const t& Invalid): _rowsize (M), _colsize (n), _invalid (invalid) {for (size_t i = 0 ; i < _rowsize; i++) {for (size_t j = 0; J < _colsize; J + +) {if (a[i*n + j]! = _invalid) {_a.push_back (triple<t> (A[i*n + j], I, j)); }}}}sparsematrix (): _rowsize (0), _colsize (0), _invalid (0) {}
There is also a matrix transpose. What is a matrix transpose?
* Matrix Transpose
Swap the rows and columns of the original matrix, that is, the data on [I][j] and [j][i] positions.
650) this.width=650; "src=" Http://s2.51cto.com/wyfs02/M01/7F/22/wKioL1cUwMWR2SnoAAASNfIM1gM678.png "title=" ~bwxm_ DQX4I0YX3TW ' __ ' $H. png "alt=" Wkiol1cuwmwr2snoaaasnfim1gm678.png "/>
sparsematrix<t> transport () {sparsematrix<t> tmp;tmp . _colsize = _rowsize; //swap row and column size tmp._rowsize = _colsize;tmp._invalid = _invalid;for (size_t i = 0; i < _colsize; i++) {size_t index = 0;while (Index < _a.size ()) {if (_a[index]._col == i) //Follow the columns in the stored triples in turn. { //find listed as 0, press into the New Order table, continue to find ... triple<t> t;t._col = _a[index]._row;t._row = _a[index]._col;t._value = _a[index]._value;tmp._a.push_back (t);} index++;}} return tmp;}
Have you found that the efficiency of normal transpose is too low and the complexity of time is too high? Its time complexity is O (number of columns * valid data rows), then I will introduce you to the quick transpose.
Fast transpose, you only need to traverse the stored valid data once. How does this work?
650) this.width=650; "src=" Http://s2.51cto.com/wyfs02/M01/7F/22/wKioL1cUwwixKk2WAAAj0qaFFxI469.png "title=" 6[ xc2@p8_% (%E (}byckzm83.png "alt=" Wkiol1cuwwixkk2waaaj0qaffxi469.png "/>
We need to derive the number of valid values for each row after the transpose and the starting position of the first valid value in each row in the compression matrix.
That
Rowcounts = {2, 0, 2, 0, 2};
Rowstart = {0, 2, 2, 4, 4};
We can see that rowstrat[0] is always 0, it's easy to find
Rowstart[i] = Rowstart[i-1] + rowcounts[i-1];
Look at the code again.
Sparsematrix<t> fasttransport () {sparsematrix<t> tmp;tmp._colsize = _rowsize; Tmp._rowsize = _colsize;tmp._invalid = _invalid;tmp._a.resize (_a.size ()); int * Rowcounts = new int[_colsize];int *rowstart = new int[_colsize];memset ( rowcounts, 0, sizeof (int) *_colsize); memset (rowstart, 0, sizeof (int) *_colsize);//statistic number size_t index = 0;while (Index < _a.size ()) {rowcounts[_a[index]._col]++;index++;} rowstart[0] = 0;for (size_t i = 1; i < _colsize; i++) { ROWSTART[I]&NBSP;=&NBSP;ROWSTART[I&NBSP;-&NBSP;1]&NBSP;+&NBSP;ROWCOUNTS[I&NBSP;-&NBSP;1];} Position index = 0;while (Index < _a.size ()) {Int rowindex = _a[index]. _col;int& start = rowstart[rowindex]; Triple<t> t;t._col = _a[index]._row;t._row = _a[index]._col;t._value = _a[index]._value;tmp._a[start] = t;start++;index++;} Delete[] rowcounts;delete[] rowstart;return tmp;}
Next we continue to print the compression matrix using the line-first principle
void Display () {size_t index = 0;for (size_t i = 0; i < _rowsize; i++) {for (size_t j = 0; J < _colsize; J + +) {if (Inde x < _a.size () &&_a[index]._row = = I&&_a[index]._col = = j) {cout << _a[index]._value << ""; ndex++;} Else{cout << _invalid << "";}} cout << Endl;} cout << Endl;}
Finally, we'll fill in the member variables of our class.
protected:vector<triple<t>> _a;size_t _rowsize;size_t _colsize; T _invalid;
it is our quick transpose. The little friends look well. I will continue to work hard ~650) this.width=650; "src=" Http://img.baidu.com/hi/jx2/j_0007.gif "alt=" J_0007.gif "/>
Matrix-----symmetric matrices and their compressed storage && sparse matrices