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:
- Line order is the main order (lower subscript takes precedence);
- Column order is the main order (higher subscripts take precedence).
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)
/**
* 在数组 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
#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
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
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
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
Among them, NIL means empty table
Let’s take a closer look
Subtable representation
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,2),(3,(4,5)))
- ((1,2),(3,(4,5)))
- ((1,2),(3,(4,5)))
exercise
Calculate address
Note the calculation by row and column
(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} Am∗n, 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+m∗n)