This chapter only requires understanding, no in-depth requirements
Array sequential storage structure and some operations
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> #define MAX_ARRAY_DIM 8 typedef int ElemType; typedef struct { ElemType *base; //Array element base address int dim; //dimension int *bounds; //array dimension bounds base address int *constants; //array image function constant base address } Array; int InitArray(Array &A, int dim, ...) { //The "variable parameter" parameter method is used here. It mainly solves the problem of indeterminate dimension. //Example: There is a 4-dimensional array, and the dimensions are: 4, 5, 6, 7 (these numbers are given at will), then, the calling method: // InitArray (ar, 4, 4, 5, 6, 7); //ar Among them, ar is also a hypothetical variable name, 4 means that the array has 4 dimensions, 4, 5, 6, 7 are the size of each dimension //If it is 5-dimensional, then this is it: //InitArray(ar, 5, first dimension, second dimension, third dimension, fourth dimension, fifth dimension); //If the dimension dim and the length of the following dimensions are legal, construct the corresponding array A and return OK. if (dim < 1 || dim > MAX_ARRAY_DIM) return 0; A.dim = dim; A.bounds = (int *) malloc(dim * sizeof(int)); if (!A.bounds) exit(0); //If the length of each dimension is legal, store it in A.bounds, and find the total number of elements of A elemtotal. int elemtotal = 1; //ap is of type va_list, which is an array that stores variable-length parameter table information. va_list ap; //dim represents the last determined parameter, and stores the following parameters in ap // va_start va_start(ap, dim); for (int i = 0; i < dim; ++i) { //Whenever a parameter is taken out, the ap pointer points to the next A.bounds[i] = va_arg(ap, int); //The variable parameter is invalid, return 0 if (A.bounds[i] < 0) return 0; // Multiply each dimension, that is, the total number of elements elemtotal *= A.bounds[i]; } // va_end va_end(ap); // allocate element space A.base = (ElemType *) malloc(elemtotal * sizeof(ElemType)); if (!A.base) exit(0); //Find the constant ci of the image function and store it in A.constants[i-1],i=1,...,dim A.constants = (int *) malloc(dim * sizeof(int)); if (!A.constants) exit(0); //The first dimension image function is 1 A.constants[dim - 1] = 1; //Starting from two dimensions, the image function = the size of the previous dimension * the size of the previous dimension image function //The following is a detailed explanation of constants for (int i = dim - 2; i >= 0; --i) { A.constants[i] = A.bounds[i + 1] * A.constants[i + 1]; } return 1; } int DeatroyArray(Array &A) { //Destroy array A. if (!A.base) return 0; free(A.base); A.base = NULL; if (!A.bounds) return 0; free(A.bounds); A.bounds = NULL; if (!A.constants) return 0; free(A.constants); A.constants = NULL; return 1; } // When locating an array element, such as requesting the value of a[2][2][4] element, according to our common sense, we can directly use // a[2][2][4] = x; to assign or take a value, but the dimension of the array defined here can be changed, such as 8 dimensions, // And the space of the array is allocated by the malloc function, and the base address is the pointer in the structure. // At this point, you can no longer use the above method to evaluate or copy. We need to get the address of the element we want to assign or value, // Get the value through the address operation. // Because it is a[3][4][5], the address of a[2][2][4] is base+2*4*5+2*5+4*1; for simplicity, // set constants in the struct int Locate(Array A, va_list ap, int &off) { //If the subscript values indicated by ap are valid, find the relative address off of the element in A //ap refers to a series of subscripts of the group, such as a[2][2][4], then this va_list is (2, 2, 4) off = 0; int ind; for (int i = 0; i < A.dim; ++i) { ind = va_arg(ap, int); //ind legal size is 0~A.bounds[i]-1 if (ind < 0 || ind >= A.bounds[i]) return 0; off += A.constants[i] * ind; } return 1; } int Value(Array A, ElemType &e, ...) { //A is an n-dimensional array, e is an element variable, followed by n subscript values //If the subscripts are not out of bounds, e is assigned the element value of the specified A, and returns 1 va_list ap; int off, result; //va_list starts after determining the parameter e va_start (ap, e); result = Locate(A, ap, off); if (result <= 0) return result; //Base address + relative address = the real address of the element e = *(A.base + off); return 1; } int Assign(Array &A, ElemType e, ...) { //A is an n-dimensional array, e is an element variable, followed by n subscript values //If the subscript is not out of bounds, assign the value of e to the specified element of A, and return 1 va_list ap; va_start (ap, e); int result, off; result = Locate(A, ap, off); if (result <= 0) return 0; *(A.base + off) = e; return 1; }
triplet order table
#define MAXSIZE 12500 //Assume the maximum number of non-zero elements is 12500 typedef int ElemType; typedef struct { int i, j; //The row subscript and column subscript of the non-zero element ElemType e; } Triple; typedef struct { Triple data[MAXSIZE + 1];//Non-zero triple table, data[0] is not used int mu, nu, tu; //The number of rows, columns and non-zero elements of the matrix } TSMatrix; int TransposeSMatrix(TSMatrix M, TSMatrix &T) { //Use the triple storage representation to find the transpose matrix T of the sparse matrix M //Time complexity O(nu*tu) //This algorithm is only suitable for the case of tu<<mu*nu T.mu = M.nu;//The number of rows is the number of columns of M T.nu = M.mu;//The number of rows with the number of columns M T.tu = M.tu;//Number of non-zero elements if (T.tu) { int q = 1; //column loop for (int col = 1; col <= M.nu; ++col) / / Find the same column subscripts in the non-zero elements, swap for (int p = 1; p <= M.tu; ++p) if (M.data[p].j == col) { T.data[q].i = M.data[p].j; T.data[q].j = M.data[p].i; T.data[q].e = M.data[p].e; ++q; } } return 1; } int FastTransposeSMatrix(TSMatrix M,TSMatrix &T){ //Use the triple sequence table storage representation to find the transpose matrix T of the sparse matrix M //This method is called fast transpose //Two auxiliary vectors are used, and there are 4 single loops in the algorithm, namely nu, tu //The total time complexity is O(nu+tu) //When the non-zero number tu and mu*nu of M are of the order of magnitude //The time complexity is O(mu*nu), which is the same as the above time complexity T.mu = M.nu; T.nu = M.mu; T.tu=M.tu; int col,q; int num [T.nu + 1]; int cpot [T.nu + 1]; cpot [1] = 1; if(T.tu){ for(col=1;col<=M.nu;++col) num[col]=0;//Initialize the column element array for(int t=1;t<=M.tu;++t) ++num[M.data[t].j];//Find the number of non-zero elements in each column of M // Find the serial number of the first non-zero element in column col in b.data //The starting sequence number of the first column is 1 //The starting serial number of the second column is the number of non-zero elements in the first column plus the starting serial number of the first column for(col=2;col<=M.nu;++col) cpot [col] = cpot [col-1] + num [col-1]; for (int p = 1; p <= M.tu; ++p) { col=M.data[p].j; q=cpot[col]; T.data[q].i=M.data[p].j; T.data[q].j=M.data[p].i; T.data[q].e=M.data[p].e; // Take the first element of the current column ++ cpot [col]; } } return 1; }
Sequence table of logical linking of rows
#define MAXSIZE 100 #define MAXRC 100 typedef int ElemType; typedef struct { int i, j; //The row subscript and column subscript of the non-zero element ElemType e; } Triple; typedef struct { Triple data[MAXSIZE + 1];//Non-zero triple table int rpos[MAXRC + 1]; //The position table of the first non-zero element of each row int mu, nu, tu; //The number of rows, columns and non-zero elements of the matrix } RLSMatrix; int MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix &Q) { //Seek the matrix product Q=M*N, which is represented by row logical link storage //The time complexity of finding all non-zero elements of Q is O(M.tu*N.tu/N.mu) //The time complexity of compressed storage is O(M.mu*N.nu) //The total time complexity is O(M.mu*N.nu+M.tu*N.tu/N.mu) //The matrix multiplication rule shows that C(i,j) = A(i,1)*B(1,j)+A(i,2)*B(2,j)+....+A(i, n)*B(n,j), // That is, C(i,j) is the sum of the products of the i-th row of A and the non-zero element of the j-th column of B. Set the accumulator temp[B column value] to save // The value of each row of the C matrix, after the end, assign the value in temp to the C matrix. if (M.nu != N.mu) return 0; //Q initialization Q.mu = M.mu; Q.nu = N.nu; Q.tu = 0; int ctemp [N.nu + 1]; int tp, q, p, t, brow, ccol; //Q is a non-zero matrix if (M.tu * N.tu != 0) { // process each row of M for (int arow = 1; arow <= M.mu; ++arow) { //Clear the accumulator of each element in the current row ctemp[arow] = 0; Q.rpos[arow] = Q.tu + 1; if (arow < M.mu) tp = M.rpos[arow + 1]; else tp = M.tu + 1; for (p = M.rpos[arow]; p < tp; ++p) { // for each non-zero element in the current row //find the line number of the corresponding element in N brow = M.data[p].j; if (brow < N.mu) t = N.rpos[brow + 1]; else t = N.tu + 1; for (q = N.rpos[brow]; q < t; ++q) { ccol = N.data[q].j;//The column number of the product element in Q ctemp[ccol] += M.data[p].e * N.data[q].e; } }//Get the non-zero element of row arow in Q for (ccol = 1; ccol <= Q.nu; ++ccol) { // Compression stores the non-zero elements of the row if (ctemp[ccol]) {//non-zero element if (++Q.tu > MAXSIZE) return 0; Q.data[Q.tu].i = arow; Q.data[Q.tu].j = ccol; Q.data[Q.tu].e = ctemp[ccol]; } } } } return 1; }
Cross-linked list storage structure and creation
typedef int ElemType; typedef struct OLNode { int i, j; ElemType e; struct OLNode *right, *down; } OLNode, * OLink; typedef struct { OLink *rhead, *chead; int mu, no, you; } CrossList; int CreateSMatrix_OL(CrossList &M) { //Create a sparse matrix M, which is represented by a cross-linked list int m, n, t, i, j, e; OLink p, q; scanf("%d%d%d", &m, &n, &t);//Enter the number of rows, columns, and non-zero elements M.mu = m; M.nu = n; M.tu = t; if (!(M.rhead = (OLink *) malloc((m + 1) * sizeof(OLink)))) exit(0); if (!(M.chead = (OLink *) malloc((n + 1) * sizeof(OLink)))) exit(0); M.rhead[m + 1] = M.chead[n + 1] = NULL;//Initialize the row and column head pointer; each row and column linked list is an empty table for (scanf("%d%d%d", &i, &j, &e); i != 0; scanf("%d%d%d", &i, &j, &e)) {//input in any order non-zero element if (!(p = (OLink) malloc(sizeof(OLNode)))) exit(0); //generate node p->i = i; p->j = j; p->e = e; if (M.rhead[i] == NULL || M.rhead[i]->j > j) { p->right = M.rhead[i]; M.rhead[i] = p; } else {//Find the insertion position in the row table for (q = M.rhead[i]; (q->right) && q->right->j < j; q = q->right); p->right = q->right; q->right = p;//Complete row insertion } if (M.chead[j] == NULL || M.chead[j]->i > i) { p->down = M.chead[j]; M.chead[j] = p; } else {//Find the insertion position in the list for (q = M.chead[j]; (q->down) && q->down->i < i; q = q->down); p->down = q->down; q->down = p;//Complete column insertion } } return 1; }
This chapter needs to understand and know the core idea of its algorithm.