contenido
Matriz dispersa (LA MATRIZ DISPERSA)
0x02 Representación de matriz dispersa
0x03 Transpose of Matrix - Transposición de una matriz
0x04 multiplicación de matrices
Matriz dispersa (LA MATRIZ DISPERSA)
0x00 ADT
Matriz dispersa: si el número de elementos distintos de cero en la matriz es mucho menor que el número de elementos cero, lo llamamos matriz dispersa
Si usa un arreglo 2D para representar una matriz dispersa, usará mucho espacio para almacenar el mismo valor (0), no solo eso, cuando la matriz es grande, esta implementación no funciona, porque la mayoría de los compiladores lo hacen. not Las matrices tienen un tamaño limitado.
0x01 ADT - matriz dispersa
0x02 Representación de matriz dispersa
Podemos representar de forma única cualquier elemento en la matriz, y podemos usar fila, columna, valor para almacenar y ubicar elementos distintos de cero en una matriz dispersa. Esta forma de almacenar una matriz dispersa se llama triple.
by a triple <row, col, value>.
Organizamos las tripletas para que los índices de fila estén en orden ascendente, y dentro de las tripletas con los mismos índices de fila, estén en orden ascendente de índices de columna.
Para asegurarnos de que la operación pueda detenerse, debemos saber el número de filas y columnas, y el número de elementos distintos de cero en la matriz.
// Sparse_Matrix Create(max_row, max_col) ::=
#define Max_TERMS 101 /* maximum number of terms +1*/
typedef struct {
int col;
int row;
int value;
} term;
term a[MAX_TERMS];
0x03 Transpose of Matrix - Transposición de una matriz
<un algoritmo simple>
por cada fila
toma el elemento y guárdalo
como un elemento transpuesto
No sabremos exactamente qué elemento está en la transposición hasta que hayamos procesado todos los elementos anteriores.
Dónde se coloca, como:
Se requieren inserciones consecutivas. Tenemos que mover los elementos para mantener el orden correcto.
Podemos evitar este movimiento de datos utilizando el índice de la columna para determinar la posición del elemento en la matriz.
Para todos los elementos en columna, coloque los elementos en elementos .
[Programa 2.8]
complejidad del tiempo:
Si , se convierte en .
Un algoritmo de transposición que utiliza una representación densa
for (j = 0; j < columns; j++)
for (i = 0; i < rows; i++)
b[j][i] = a[i][j];
complejidad del tiempo:
Mejores algoritmos usando un poco más de espacio de almacenamiento
fast_transpose
El algoritmo primero determina el número de elementos en cada columna de la matriz original.
Este número da el número de elementos en cada fila de la matriz transpuesta.
complejidad del tiempo:
si ,
entonces se convierte
Se utilizan matrices adicionales, terminos_de_fila y pos_inicial.
Si colocamos la posición inicial en el espacio utilizado por row_terms, podemos reducir el espacio a una matriz.
0x04 Multiplicación de matrices
Dadas dos sumas de matrices , donde es y es
La matriz del producto es , y sus elementos son:
<Algoritmo de multiplicación de matrices usando notación densa>
for (i = 0; i < rows_a; i++) {
for (j = 0; j < cols_b; j++) {
sum = 0;
for (k = 0; k < cols_a; k++)
sum += a[i][k]*b[k][j];
d[i][j] = sum;
}
}
complejidad del tiempo:
Tenga en cuenta que es posible que el producto de dos matrices dispersas ya no lo sea. P.ej:
[Programa 2.10]
Las matrices se almacenan por separado en matrices y la transposición se almacena en new_b.
Usar variables variables:
row - 目前正在与B的列相乘的A的行
row_begin - 当前行的第一个元素在a中的位置
column - 目前正在与A的某一行相乘的B的列
totald - 乘积矩阵D的当前元素数
i, j - 用于连续检查A行和B列中的元素的指针
void mmult(term a[], term b[], term d[])
/* multiply two sparse matrices */
{
int i, j, column, totalb = b[0].value, totald = 0;
int rows_a = a[0].row, cols_a = a[0].col, totala = a[0].value;
int cols_b = b[0].col;
int row_begin = 1, row = a[1].row, sum = 0;
term new_b[MAX_TERMS];
if (col_a != b[0].row) {
fprintf(stderr, “Incompatible matrices\n”);
exit(1);
}
fast_transpose(b, new_b);
/* set boundary condition */
a[totala+1].row = rows_a;
new_b[totalb+1].row = cols_b; new_b[totalb+1].col = -1;
for (i = 1; i <= totala; ) {
column = new_b[1].row;
for (j = 1; j <= totalb+1; ) {
/* multiply row of a by column of b */
if (a[i].row != row) {
storesum(d, &totald, row, column, &sum);
i = row_begin;
for ( ; new_b[j].row == column; j++)
;
column = new_b[j].row;
}
else if (new_b[j].row != column) {
storesum(d, &totald, row, column, &sum);
i = row_begin;
column = new_b[j].row;
}
else switch (COMPARE(a[i].col, new_b[j].col)) {
case –1 : /* go to next term in a */
i++; break;
case 0 : /* add terms, go to next term in a and b */
sum += (a[i++].value * new_b[j++].value);
break;
case 1 : /* go to next term in b */
j++;
}
} /* end of for j <= totalb+1 */
for ( ; a[i].row == row; i++)
;
row_begin = i; row = a[i].row;
} /* end of for i <= totala */
d[0].row = row_a; d[0].col = cols_b;
d[0].value = totald;
}
Tenga en cuenta que introducimos un elemento adicional tanto en a como en new_b:
a[totala+1].row = rows_a;
new_b[totalb+1].row = cols_b;
new_b[totalb+1].col = -1;
complejidad del tiempo
Antes del bucle for:
fast transpose - O(cols_b + totalb) time.
El bucle for externo se itera filas_a veces:
En cada iteración, el bucle for interno calcula una fila de la matriz de productos D; en cada iteración, i o j se incrementan en 1, o i se restablece a row_begin
El incremento total máximo de j es totalb+1. Luego, cuando se procesa la k-ésima fila, i puede incrementarse como máximo varias veces, y se restablece a cols_b veces de row_begin como máximo. Por lo tanto, el incremento total máximo de i es cols_b-. El bucle for interno toma tiempo y las columnas se restablecen. Por lo tanto, el bucle for externo debe
Vale la pena señalar que si y , entonces su complejidad temporal se convierte en .