universidad de carabobo facultad experimental de ciencias y

Anuncio
UNIVERSIDAD DE CARABOBO
FACULTAD EXPERIMENTAL DE CIENCIAS Y TECNOLOGÍA
DEPARTAMENTO DE COMPUTACIÓN
ALGORITMOS Y PROGRAMACIÓN II
TEMA 6
ESTRUCTURAS MULTIENLAZADAS
Matrices Esparcidas
Abril, 2005
Matrices Esparcidas: Definiciones y Conceptos Básicos
En diversas aplicaciones que involucran matrices puede darse el caso que muchos elementos de la
matriz sean no significativos. Este tipo de matrices, cuyo contenido está formado en su mayoría por
elementos no significativos, se denomina matriz esparcida.
Utilizando la representación enlazada es posible almacenar solamente los elementos significativos de
la matriz, lo que resultaría en un ahorro de espacio en memoria.
La estructura es la siguiente: Para permitir el acceso a cualquier fila o columna de la matriz, cada
elemento significativo de la matriz aparece en dos listas, una para su fila y otra para su columna.
Cada nodo contiene dos apuntadores, uno al elemento significativo siguiente en su fila y otro para el
elemento significativo siguiente en su columna. Además, cada nodo contiene campos con el índice
de su fila, el índice de su columna y el valor del elemento.
Por lo tanto, cada nodo presenta la siguiente estructura:
•
•
•
•
•
elem: Valor del elemento en esa posición de la matriz.
fila: Indice de la fila en esa posición de la matriz.
col: Indice de la columna en esa posición de la matriz.
sig_fila: apuntador al siguiente nodo en la misma fila.
sig_col: apuntador al siguiente nodo en la misma columna.
La representación gráfica de un nodo de una matriz esparcida puede apreciarse en la figura 1. El
significado de cada campo es el descrito con anterioridad.
fila
sig_col
col
elem
sig_fila
Figura 1: Campos de un nodo
Considere, por ejemplo, una matriz M de números reales en la cual la mayoría de sus elementos son iguales a
cero.
0 2.5 0 
 1.0 0


0 
 0 1.3 2.1 0
M=
3.4 0
0 0.2 0 


 0
0
0
0 7.6 

La matriz esparcida correspondiente a M se define gráficamente como se muestra en la figura 2.
1
1
1
2
1 1.0
2
2
3
3
3
1 3.4
2 1.3
2
4
1
4 2.5
3
4 0.2
5
3 2.1
4
4
5 7.6
Figura 2: Representación de una matriz M de números reales en forma encadenada
ESPECIFICACIÓN ALGEBRÁICA
Sintaxis
vacía :
agregar_elem :
eliminar _elem:
existe_elem :
modificar_elem :
consultar_elem :
num_filas:
num_cols:
existe_fila:
existe_col:
Mat_Esp × Elemento × Natural × Natural
Mat_Esp × Natural × Natural
Mat_Esp × Natural × Natural
Mat_Esp × Elemento × Natural × Natural
Mat_Esp × Natural × Natural
Mat_Esp
Mat_Esp
Mat_Esp × Natural
Mat_Esp × Natural
ESPECIFICACIÓN O PERACIONAL
Semántica
{ Pre: }
proc vacía (var M: Mat_Esp)
{ Post: M´es una matriz esparcida vacía }
→
→
→
→
→
→
→
→
→
→
Mat_Esp
Mat_Esp
Mat_Esp
Logical
Mat_Esp
Elemento
Natural
Natural
Logical
Logical
{ Pre: existe_fila(M,i) ∧ existe_col(M,,j) ∧ ¬existe(M, i, j) }
proc agregar (var M : Mat_Esp; e : Elemento; i, j : Integer)
{ Post: M´ es una matriz esparcida tal que existe(M', i, j) ∧ (consultar(M', i, j) = e) }
{ Pre: existe(M, i, j) }
proc eliminar (var M : Mat_Esp; i, j : Integer)
{ Post: M´es una matriz esparcida tal que ¬existe(M', i, j) }
{ Pre: }
func existe (M : Mat_Esp; i, j : Integer) : Logical;
{ Post: existe ← ∃i ∃j (consultar(M, i, j) = elemento significativo }
{ Pre: existe(M, i, j) }
proc modificar (M : Mat_Esp; e : Elemento; i, j : Integer) : Mat_Esp;
{ Post: M´es una matriz esparcida tal que (consultar(M', i, j) = e) }
{ Pre: existe(M, i, j) }
func consultar (M : Mat_Esp; i, j : Integer) : Elemento;
{ Post: consultar ← Mij }
Implementación de la class Mat_Esp
Representación Estática
En esta implementación se utilizan arreglos para manejar los índices de las filas y columnas de la matriz.
Además, se supone que se cumplen todas las precondiciones planteadas en la especificación pre/post de cada
operación.
class nodo
begin
private:
elem
fila
col
sig_fila
sig_col
:
:
:
:
:
elemento;
integer;
integer;
pointer to nodo;
pointer to nodo;
public:
nodo();
~nodo();
end
Func
Func
Func
Func
Func
get_elem()
get_fila()
get_col()
get_sig_fil()
get_sig_col()
proc
proc
proc
proc
proc
set_elem(in e : elemento);
set_fila(in ind : integer);
set_col(in ind : integer);
set_sig_fila(in p : pointer to nodo);
set_sig_col(in p : pointer to nodo);
:
:
:
:
:
elemento;
integer;
integer;
pointer to nodo;
pointer to nodo;
nodo::nodo()
begin
fila
col
sig_fila
sig_col
end
=
=
=
=
0;
0;
NULL;
NULL;
Func nodo::get_elem() : elemento
begin
return elem;
end
Func nodo::get_fila() : integer
begin
return fila;
end
Func nodo::get_col() : integer
begin
return col;
end
Func nodo::get_sig_fil() : pointer to nodo
begin
return sig_fil;
end
Func nodo::get_sig_col() : pointer to nodo;
begin
return sig_col;
end
proc nodo::set_elem(in e : elemento)
begin
elem e;
end
proc nodo::set_fila(in ind : integer)
begin
fila ind;
end
proc nodo::set_col(in ind : integer)
begin
col ind;
end
proc nodo::set_sig_fila(in p : pointer to nodo)
begin
sig_fila p;
end
proc nodo::set_sig_col(in p : pointer to nodo)
begin
sig_col p;
end
const
MAX_M = ?
MAX_N = ?
class MatEsp
begin
private:
filas
: array [1..MAX_M] of pointer to nodo;
columnas : array [1..MAX_N] of pointer to nodo;
public:
MatEsp();
~MatEsp();
func existe(in i, j : integer) : logical;
func consultar(in i, j : integer) : elemento;
func num_filas() : integer;
func num_cols() : integer;
proc agregar(in e : elemento; in i, j : integer);
proc eliminar(in i, j : integer);
proc modificar(in e : elemento; in i, j : integer);
end
MatEsp::MatEsp()
begin
i : integer;
for i in [1..MAX_M] do
begin
filas[i] NULL;
end
end
for i in [1..MAX_N] do
begin
columnas[i] NULL;
end
Agregar un elemento en la i−ésima fila y j−ésima columna
Pasos a seguir:
• Localizar en la lista asociada a la fila i el primer nodo que contenga un índice de columna mayor que j,
referenciando también al nodo anterior si existe.
• Insertar el nodo creado en la lista de la fila i en la posición adecuada.
• Localizar en la lista asociada a la columna j el primer nodo que contenga un índice de fila mayor que i,
referenciando también al nodo anterior si existe.
• Insertar el nodo creado en la lista de la columna j en la posición adecuada.
proc MatEsp::agregar(in e : elemento; in i, j : integer)
begin
P, ant, aux : pointer to nodo;
log : logical;
P ← filas[i];
log ← false;
end
while (P ≠ NULL) ∧ ¬log do
begin
if (j < P↑.get_col()) then
log ← true
else
ant ← P;
P ← P↑.get_sig_fila()
end if
end
aux = new nodo;
aux↑.set_elem(e);
aux↑.set_fila(i);
aux↑.set_col(j);
aux↑.set_sig_fila(P);
if (P = filas[i]) then
filas[i] ← aux ;
else
ant↑.set_sig_fila(aux);
end if;
P ← columnas[j];
log ← false;
while (P ≠ NULO) ∧ ¬log do
if (i < P↑.get_fila()) then
log ← true;
else
ant ← P;
P ← P↑.get_sig_col();
end if
end
aux↑.set_sig_col(P);
if (P = columnas[j]) then
columnas[j] ← aux;
else
ant↑.sig_col ← aux;
end if
Queda como ejercicio el desarrollo del
resto de las operaciones de la class
MatEsp
Representación Dinámica
En esta implementación se utilizan listas para manejar los índices de las filas y columnas de la matriz. Además,
se supone que se cumplen todas las precondiciones planteadas en la especificación pre/post de cada
operación.
class nodo_interno
begin
private:
elem
: elemento;
sig_fila : pointer to
sig_col : pointer to
fila
: pointer to
col
: pointer to
nodo_interno;
nodo_interno;
nodo_fila;
nodo_columna;
public:
nodo_interno();
~nodo_interno();
func
func
func
func
func
end
get_elem()
get_sig_fil()
get_sig_col()
get_fila()
get_col()
:
:
:
:
:
elemento;
pointer to
pointer to
pointer to
pointer to
nodo_interno;
nodo_interno;
nodo_fila;
nodo_columna;
proc set_elem(in e : elemento);
proc set_sig_fila(in p : pointer to nodo_interno);
proc set_sig_col(in p : pointer to nodo_interno);
nodo_interno::nodo_interno()
begin
sig_fila = NULL;
sig_col = NULL;
end
func nodo_interno::get_elem() : elemento
begin
return elem;
end
func nodo_interno::get_sig_fil() : pointer to nodo_interno
begin
return sig_fil;
end
func nodo_interno::get_sig_col() : pointer to nodo_interno
begin
return sig_col;
end
func nodo_interno::get_fila() : pointer to nodo_fila
begin
return fila;
end
func nodo_interno::get_col() : pointer to nodo_columna
begin
return col;
end
proc nodo_interno::set_elem(in e : elemento)
begin
elem e;
end
proc nodo_interno::set_sig_fila(in p : pointer to nodo_interno)
begin
sig_fila p;
end
proc nodo_interno::set_sig_col(in p : pointer to nodo_interno)
begin
sig_col p;
end
class nodo_fila
begin
private:
info
: info_fila;
sig_fila
: pointer to nodo_fila;
prim_nodo
: pointer to nodo_interno;
public:
nodo_fila();
~ nodo_fila();
func get_info()
: info_fila;
func get_fila()
: integer;
func get_sig_fila() : pointer to nodo_fila;
func get_prim_nodo() : pointer to nodo_interno;
proc set_fila(in inf : integer);
proc set_sig_fila(in p : pointer to nodo_fila);
proc set_prim_nodo(in p : pointer to nodo_interno);
end
nodo_fila::nodo_fila()
begin
info 0;
sig_fila NULL;
prim_nodo NULL;
end
func nodo_fila::get_info() : info_fila
begin
return info;
end
func nodo_fila::get_fila() : integer
begin
return info.ind;
end
func nodo_fila::get_sig_ind() : pointer to nodo_fila
begin
return sig_fila;
end
func nodo_fila::get_prim_nodo() : pointer to nodo_interno
begin
return prim_nodo;
end
proc nodo_fila::set_fila(in inf : integer)
begin
info.ind inf;
end
proc nodo_fila::set_sig_fila(in p : pointer to nodo_fila)
begin
sig_fila p;
end
proc nodo_fila::set_prim_nodo (in p : pointer to nodo_interno)
begin
prim_nodo p;
end
class nodo_columna
begin
private:
info
: info_fila;
sig_columna : pointer to nodo_columna;
prim_nodo
: pointer to nodo_interno;
public:
nodo_columna();
~nodo_columna();
func
func
func
func
end
get_info()
get_columna()
get_sig_columna()
get_prim_nodo()
:
:
:
:
info_columna;
integer;
pointer to nodo_columna;
pointer to nodo_interno;
proc set_columna(in inf : integer);
proc set_sig_columna(in p : pointer to nodo_columna);
proc set_prim_nodo(in p : pointer to nodo_interno);
nodo_columna::nodo_columna()
begin
info 0;
sig_columna NULL;
prim_nodo NULL;
end
func nodo_columna::get_info() : info_columna
begin
return info;
end
func nodo_columna::get_columna() : integer
begin
return info.ind;
end
func nodo_columna::get_sig_ind() : pointer to nodo_columna
begin
return sig_columna;
end
func nodo_columna::get_prim_nodo() : pointer to nodo_interno
begin
return prim_nodo;
end
proc nodo_columna::set_columna(in inf : integer)
begin
info.ind inf;
end
proc nodo_columna::set_sig_columna(in p : pointer to nodo_columna)
begin
sig_columna p;
end
proc nodo_columna::set_prim_nodo (in p : pointer to nodo_interno)
begin
prim_nodo p;
end
class MatEsp
begin
private:
filas
: pointer to nodo_fila;
columnas : pointer to nodo_columna;
public:
func existe(in i, j : integer) : logical;
func consultar(in i, j : integer) : elemento;
func num_filas() : integer;
func num_cols() : integer;
end
proc agregar(in e : elemento; in i, j : integer);
proc eliminar(in i, j : integer);
proc modificar(in e : elemento; in i, j : integer);
MatEsp::MatEsp()
begin
filas
NULL;
columnas NULL;
end
Queda como ejercicio el desarrollo del
resto de las operaciones de la class
MatESP
Descargar