Data Structures and Algorithms Chapter 5 [Arrays and Generalized Tables]

array

Basic operations

InitArray(&A, n, bound1, ..., boundn)

DestroyArray(&A)

Value(A, &e, index1, ..., indexn)

Assign(&A, e, index1, ..., indexn)

Array sequence representation

Two ways of sequential mapping:

  1. Line order is the main order (lower subscript takes precedence);
  2. Column order is the main order (higher subscripts take precedence).

Insert image description here

but n n nNumber combination:LOC(x1, x2, ..., xn) = LOC(0, 0, ..., 0) + [(x1 × b1 + x2) × b2 + x3] × b3 + ... + xn

Data type definition

#include <stdarg.h> // 标准头文件,提供宏 va_start、va_arg 和 va_end,用于存取变长参数表

#define MAX_ARRAY_DIM 8 // 假设数组维数的最大值为 8

typedef struct {
    
    
    ElemType *base;  // 数组元素地址,由 InitArray 分配
    int dim;         // 数组维数
    int *bounds;     // 数组维界基址,由 InitArray 分配
    int *constants;  // 数组映像函数常量基址,由 InitArray 分配
} Array;

in:

Status InitArray(Array& A, int dim, ...) {
    
    
    // 若维数 dim 不合法,则返回 ERROR
    if (dim < 1 || dim > MAX_ARRAY_DIM) {
    
    
        return ERROR;
    }
    A.dim = dim;
    A.bounds = (int*)malloc(dim * sizeof(int));
    if (!A.bounds) {
    
    
        exit(OVERFLOW);
    }
    // 存储各维长度,并计算元素总数 elemtotal
    int elemtotal = 1;
    va_list ap;  // 定义 va_list 类型变量 ap,用于存放变长参数表信息的数组
    va_start(ap, dim);  // 初始化 ap 数组
    for (int i = 0; i < dim; ++i) {
    
    
        A.bounds[i] = va_arg(ap, int);
        if (A.bounds[i] < 0) {
    
    
            return UNDERFLOW;
        }
        elemtotal *= A.bounds[i];
    }
    va_end(ap);  // 结束 ap 数组

    A.base = (ElemType*)malloc(elemtotal * sizeof(ElemType));
    if (!A.base) {
    
    
        exit(OVERFLOW);
    }
    // 求映像函数的常数 ci,并存入 A.constants[i-1],i=1,...,dim
    A.constants = (int*)malloc(dim * sizeof(int));
    if (!A.constants) {
    
    
        exit(OVERFLOW);
    }
    A.constants[dim - 1] = 1;
    // L=1,指针的增减以元素的大小为单位
    for (int i = dim - 2; i >= 0; --i) {
    
    
        A.constants[i] = A.bounds[i + 1] * A.constants[i + 1];
    }
    return OK;  // 返回 OK
}

A.bounds is how many elements can be placed in each dimension:a[A.bounds[0]][A.bounds[1]][A.bounds[2]]……
A.constants is a pointer to the element at the beginning of each dimension (because it is stored sequentially, it is not stored in the computer There is no obvious distinction between dimensions, you need to calculate the pointer to the first element of each dimension yourself)

Explanation about va_list

/**
 * 在数组 A 中定位指定下标的元素,并计算出该元素的相对地址。
 * 
 * @param A     要定位的多维数组
 * @param ap    指示要定位的下标列表的可变参数
 * @param off   返回该元素在数组 A 中的相对地址
 * @return      如果下标合法,返回 OK;否则返回 OVREFLOW
 */
Status Locate(Array A, va_list ap, int& off) {
    
    
    // 初始化偏移量为 0
    off = 0;
    // 循环遍历所有维度
    for (int i = 0; i < A.dim; ++i) {
    
    
        // 获取当前维度的下标值
        int ind = va_arg(ap, int);  
        // 检查下标值是否超出边界
        if (ind < 0 || ind >= A.bounds[i]) {
    
    
            return OVREFLOW;
        }
        // 计算该维度下标对应的偏移量,并累加到总偏移量中
        off += A.constants[i] * ind;
    }
    // 如果下标合法,则返回 OK
    return OK;
}

Compressed storage of matrices

Insert image description here

#define MAXSIZE 12500

typedef union {
    
    
    Triple data[MAXSIZE + 1]; // 用于存储稀疏矩阵中的非零元素
    int mu, nu, tu; // 分别表示稀疏矩阵的行数、列数和非零元素个数
} TSMatrix; // 稀疏矩阵类型

There are 2 types of sparse matrices:

  • There are certain rules for the distribution of non-zero elements in matrices
    For example: triangular matrix, diagonal matrix
  • Random sparse matrix
    Non-zero elements appear randomly in the matrix

Compression storage method of random sparse matrix:

  • triple sequence table

This structure is generally used to represent non-zero elements in sparse matrices. For a sparse matrix with m rows and n columns, if the number of non-zero elements is k, a Triple array of length k can be used to store these non-zero elements.

#define MAXSIZE 12500

typedef struct {
    
    
    int i, j; // 该非零元的行下标和列下标
    ElemType e; // 该非零元的值
} Triple; // 三元组类型
  • Sequential table of row logical joins
  • cross linked list

Find the transposed matrix

triplet transpose

Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T){
    
    
    T.mu = M.nu;
    T.nu = M.mu;
    T.tu = M.tu;
    if (T.tu) {
    
    
        int col, t, p;
        int num[MAXSIZE + 1] = {
    
    0}; // 列计数器,用于记录每列非零元素的个数
        int cpot[MAXSIZE + 1] = {
    
    0}; // 行指针数组,用于记录每列第一个非零元素在转置矩阵中的位置
        // 统计每列非零元素的个数
        for (col = 1; col <= M.nu; ++col) {
    
    
            num[col] = 0;
        }
        for (t = 1; t <= M.tu; ++t) {
    
    
            ++num[M.data[t].j];
        }
        // 计算每列第一个非零元素在转置矩阵中的位置
        cpot[1] = 1;
        for (col = 2; col <= M.nu; ++col) {
    
    
            cpot[col] = cpot[col - 1] + num[col - 1];
        }
        // 执行转置操作
        for (p = 1; p <= M.tu; ++p) {
    
    
            col = M.data[p].j;
            int 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;
            ++cpot[col]; // 该列的行指针加1
        }
    }
    return OK;
} // FastTransposeSMatrix

Sequential table of logically connected rows

#define MAXMN 500

typedef struct {
    
    
    Triple data[MAXSIZE + 1]; // 非零元三元组表
    int rpos[MAXRC + 1]; // 各行第一个非零元的位置表
    int mu, nu, tu;  // 矩阵的行数、列数和非零元个数            
} RLSMatrix; // 行逻辑链接顺序表类型
ElemType value(RLSMatrix M, int r, int c) {
    
    
    int p = M.rpos[r];
    while (M.data[p].i == r && M.data[p].j < c) {
    
    
        p++;
    }
    if (M.data[p].i == r && M.data[p].j == c) {
    
    
        return M.data[p].e;
    } else {
    
    
        return 0;
    }
} // value

Matrix multiplication:

// 稀疏矩阵相乘
Status MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix &Q) {
    
    
    // 如果两个稀疏矩阵的列数不等,则无法相乘,返回错误状态
    if (M.nu != N.mu) {
    
    
        return ERROR;
    }
    // 计算结果矩阵Q的行数,列数以及非零元素个数
    Q.mu = M.mu;
    Q.nu = N.nu;
    Q.tu = 0;
    // 如果M、N之间存在非零元素,则进行矩阵相乘的处理
    if (M.tu * N.tu != 0) {
    
    
        // 遍历M的每一行
        for (int arow = 1; arow <= M.mu; ++arow) {
    
    
            // M矩阵中第arow行在三元组表中的起始位置
            int mp = M.rpos[arow];
            // 遍历N的每一列
            for (int bcol = 1; bcol <= N.nu; ++bcol) {
    
    
                // 初始化N矩阵中第bcol列在三元组表中的起始位置
                int np = N.rpos[bcol];
                // 累加M矩阵第arow行和N矩阵第bcol列的乘积
                ElemType temp = 0;
                while (mp < M.tu && np < N.tu) {
    
    
                    // 如果M矩阵和N矩阵中的当前位置元素在同一列,则累加乘积
                    if (M.data[mp].j == N.data[np].i) {
    
    
                        temp += M.data[mp].e * N.data[np].e;
                        mp++;
                        np++;
                    } else if (M.data[mp].j < N.data[np].i) {
    
    
                        mp++;
                    } else {
    
    
                        np++;
                    }
                } // while
                // 如果累加的乘积不为0,则添加到结果矩阵Q中
                if (temp != 0) {
    
    
                    Q.tu++;
                    // 将非零元素添加到Q三元组表的末尾
                    Q.data[Q.tu].i = arow;
                    Q.data[Q.tu].j = bcol;
                    Q.data[Q.tu].e = temp;
                }
            } // for bcol
        } // for arow
    } // if
    return OK;
} // MultSMatrix

cross linked list

Insert image description here

Structure definition

typedef struct OLNode {
    
    
    int i, j;       // 该非零元的行和列下标 
    ElemType e;     // 该非零元的值 
    struct OLNode *right, *down;   // 该非零元所在行表和列表的后继指针 
} OLNode, *OLink;

typedef struct {
    
    
    OLink *rhead, *chead;   // 行和列链表头,指向 rhead 与 chead 数组
                            // 指针向量基址由 CreateSMatrix 函数分配
    int mu, nu, tu;         // 稀疏矩阵的行数、列数和非零元个数      
} CrossList;

generalized table

Insert image description here
Structural features:

  • The length of a generalized table is defined as the number of elements contained in the outermost layer;
  • The depth of a generalized table is defined as the multiplicity of included brackets;
    Note: The depth of an "atom" is 0; the depth of an "empty table" is 1

Insert image description here
The parentheses need to be removed from the head of the table, and the original parentheses must be taken directly from the end of the table and included.

Storage structure of generalized table

Header and footer method

Insert image description here
Among them, NIL means empty table
Insert image description here
Let’s take a closer look

Subtable representation

Insert image description here
Insert image description here

Note that0|x is followed by0|y, instead of following the tail of the table, this time the elements at the back of the table are taken out, so the difference between it and the head and tail notation is this, It also takes the following sub-table Remove the outer parentheses

It is easier to understand with this example

find depth

int GlistDepth(Glist L) {
    
    
    // 返回指针L所指的广义表的深度
    int max = 0;
    Glist pp;
    int dep;
    if(!L) return 1;
    if(L->tag==ATOM) return 0;
    for (pp = L; pp; pp = pp->ptr.tp) {
    
    
        dep = GlistDepth(pp->ptr.hp);
        if (dep > max) {
    
    
            max = dep;
        }
    }
    return max + 1;
} // GlistDepth

When you encounter some fill-in-the-blank questions that require depth, you may have to draw them yourself, as they cannot be seen with your eyes.

For example: generalized table { {1,2},{3,{4,5}}}, subtables {1,2} and {3,{4,5}} are located in the same layer. This generalization The table contains 3 levels of brackets, so the depth is 3.

  1. ((1,2),(3,(4,5)))
  2. ((1,2),(3,(4,5)))
  3. ((1,2),(3,(4,5)))

exercise

Calculate address

Insert image description here
Insert image description here
Note the calculation by row and column
Insert image description here
(1) 100 (2) 776 (3) 1784 (4) 4416

a3125—— 3×3×5×8+1×5×8+2×8+5
高维的系数乘以低维所包含的元素数

5.19 Saddle Point

和矩阵 A A Aneutral certain element aij This is the first i i The minimum value in row i is also the minimum value in row j j j is the maximum value in the column, then this element is called a saddle point in the moment. Assume that the matrix is ​​stored in a two-dimensional array A m ∗ n A_{m*n} Amn, try to write an algorithm to find all saddle points in the matrix, and analyze the time complexity of your algorithm in the worst case

void saddle(int a[m][n]) {
    
    
    int flag = 0, min, col;
    for (int i = 0; i < m; ++i) {
    
    
        min = a[i][0];
        for (int j = 0; j < n; ++j) {
    
    
            if (a[i][j] < min) {
    
    
                min = a[i][j];
                col = j;
            }
        }
        int flag1 = 1;
        for (int k = 0; k < m; ++k) {
    
    
            if (min < a[k][col]){
    
    
                flag1 = 0;
                break;
            }
        }
        if (flag1) {
    
    
            printf("%d行%d列是马鞍点,值为%d\n", i, col, min);
            flag = 1;
        }

    }
    if (!flag) {
    
    
        printf("无马鞍点\n");
    }
}

Time complexity: O ( m 2 + m ∗ n ) O(m^2+m*n) O(m2+mn)

Guess you like

Origin blog.csdn.net/qq_61786525/article/details/131054707