Data Structures (written by Yan Weimin in C language) - Arrays and Generalized Tables

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.




Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325807138&siteId=291194637