Вы находитесь на странице: 1из 21

Leccin 7:

Listas doblemente enlazadas.


Listas circulares y matrices
dispersas
Motivacin
Listas doblemente enlazadas
Inserciones y borrados
Iteracin en listas doblemente enlazadas
Listas circulares
Matrices dispersas

Motivacin
Estamos implementando un editor de textos sencillo
Un documento est formado por un conjunto de lneas, cada
una de ellas formadas por un conjunto de caracteres
Usaremos una lista para las lneas y un vector dinmico
Hay problemas tanto al dar enter
para guardar el contenido de cada lnea
como para mover

el cursor hacia arriba porque habra


que volver a recorrer la lista
Lorem ipsum ad his scripta blandit partiendo,

Lorem ipsum ad his scripta blandit partiendo,


eum fastidii accumsan euripidis in, eum liber
hendrerit an. Qui ut wisi vocibus suscipiantur,
quo dicit ridens inciderint id.

linea activa

eum fastidii accumsan euripidis in, eum liber

cursor
hendrerit an. Qui ut wisi vocibus suscipiantur,

quo dicit ridens inciderint id.

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

Motivacin
Esta estructura permite aadir lineas en cualquier posicin y
modificar una linea aadiendo, borrando o modificando
caracteres
Sin embargo conforme se edita el texto, la estructura de
datos facilita el pasar de una lnea a la siguiente, pero no a la
anterior
La lista enlazada no es suficientemente flexible

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

Listas doblemente enlazadas

Una lista doblemente enlazada es similar a las


listas que ya conocemos, con la diferencia de cada
nodo tiene adems un puntero al nodo anterior
Este detalle garantiza O(1) en la insercin y
borrado en cualquier posicin, adems de permitir
iteracin bidireccional

ListaDEnlazada
cabecera
cola

0
dato1

dato2

dato3

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

Nodos doblemente enlazados


Al haber dos punteros, (de 32 o 64 bits) puede gastarse demasiada memoria

template<class
template<class T>
T>
class
class Nodo
Nodo {{
public:
public:
TT dato;
dato;
Nodo
Nodo *ant,
*ant, *sig;
*sig;

};
};

Nodo(T
Nodo(T &aDato,
&aDato, Nodo
Nodo *aAnt,
*aAnt, Nodo
Nodo *aSig):
*aSig):
dato(aDato),
dato(aDato), ant(aAnt),
ant(aAnt), sig(aSig)
sig(aSig) {}
{}
Nodo es una clase oculta, por lo que da igual que est todo pblico porque nadie va a manipularla

ant

dato

sig

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

Insercin al principio
0
Nodo<T>
Nodo<T> *nuevo;
*nuevo;
nuevo
=
nuevo = new
new Nodo<T>(dato,
Nodo<T>(dato, 0,
0, cabecera);
cabecera);

nuevo

dato

cabecera
dato 1

//
// Caso
Caso especial:
especial: si
si la
la lista
lista estaba
estaba
//
// vaca,
vaca, poner
poner la
la cola
cola apuntando
apuntando al
al nodo
nodo
if
if (cola
(cola ==
== 0)
0)
cola
cola == nuevo;
nuevo;
if
if (cabecera
(cabecera !=
!= 0)
0)
cabecera->ant
cabecera->ant == nuevo
nuevo
cabecera
cabecera == nuevo;
nuevo;

0
0
nuevo

dato

cabecera
dato 1

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

Insercin al final

Es simtrico a la insercin al principio

Nodo<T>
Nodo<T> *nuevo;
*nuevo;
nuevo
nuevo == new
new Nodo<T>(dato,
Nodo<T>(dato, cola,
cola, 0);
0);

nuevo
cola
...

//
// Caso
Caso especial:
especial: si
si la
la lista
lista estaba
estaba vaca,
vaca,
//
// poner
poner la
la cola
cola apuntando
apuntando al
al nodo
nodo
if
if (cabecera
(cabecera ==
== 0)
0)
cabecera
cabecera == nuevo;
nuevo;
if
if (cola
(cola !=
!= 0)
0)
cola->sig
cola->sig == nuevo
nuevo
cola
=
nuevo
cola = nuevo

nuevo
cola
...

dato

dato n

dato

dato n

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

0
7

Insercin en medio
Hacer mdulos difciles internamente, pero interfaz sencilla fuera.

dato

nuevo
Nodo<T>
Nodo<T>
nuevo
nuevo ==

*nuevo;
*nuevo;
new
new Nodo<T>(dato,
Nodo<T>(dato, p->ant,
p->ant, p);
p);

...

Importante el orden de estas operaciones para que no se pierdan

p->ant->sig
p->ant->sig == nuevo;
nuevo;
p->ant
=
nuevo;
p->ant = nuevo;
si el orden inverso:
p->ant = nuevo;
p->ant->ant->sig = nuevo;
// equivalente a
nuevo->ant->sig = nuevo

...

dato i

dato i+1

...

dato i+1

...

dato

nuevo

p
dato i

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

Borrar el primer nodo


borrado

Nodo<T>
Nodo<T> *borrado
*borrado == cabecera;
cabecera;

dato 1

dato 2

...

dato 2

...

texto

cabecera
cabecera
cabecera == cabecera->sig
cabecera->sig
delete
borrado
delete borrado

borrado

if
if (cabecera
(cabecera !=
!= 0)
0)
cabecera->ant
cabecera->ant == 00
else
else
cola
cola == 00

dato 1

cabecera

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

Borrados al final y en medio

El borrado al fnal es simtrico al borrado del primer


nodo
El borrado en medio tampoco plantea especiales
difcultades
Ejercicio propuesto: resolver en papel el borrado en
medio y al fnal

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

10

Iteracin

Los iteradores en una lista enlazada soportan las


dos direcciones
Este es el puntero p de las anteriores transparencias

template<class
template<class T>
T>
class
Iterador
{
class Iterador {
Nodo<T>
Nodo<T> *nodo;
*nodo;
friend
class
friend class ListaDEnlazada;
ListaDEnlazada;
public:
public:
Iterador(Nodo<T>
Iterador(Nodo<T> *aNodo)
*aNodo) :: nodo(aNodo)
nodo(aNodo) {}
{}
bool
bool
bool
bool
void
void
void
void
};
};

hayAnterior()
hayAnterior() {{ return
return nodo
nodo !=
!= 0;
0; }}
haySiguiente()
haySiguiente() {{ return
return nodo
nodo !=
!= 0;
0; }}
anterior()
anterior() {{ nodo
nodo == nodo->ant;
nodo->ant; }}
siguiente()
siguiente() {{ nodo
nodo == nodo->sig;
nodo->sig; }}

TT &dato()
&dato() {{ return
return nodo->dato;
nodo->dato; }}

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

11

La interfaz de la clase
ListaDEnlazada
template<class
template<class T>
T>
class
ListaDEnlazada
class ListaDEnlazada {{
Nodo<T>
Nodo<T> *cabecera,
*cabecera, *cola;
*cola;
public:
public:
ListaDEnlazada()
ListaDEnlazada() :: cabecera(0),
cabecera(0), cola(0)
cola(0) {}
{}
~ListaDEnlazada();
~ListaDEnlazada();
ListaDEnlazada(const
ListaDEnlazada(const ListaDEnlazada
ListaDEnlazada &l);
&l);
ListaDEnlazada
&operator=(ListaDEnlazada
ListaDEnlazada &operator=(ListaDEnlazada &l);
&l);

};
};

Iterador<T>
Iterador<T> iteradorInicio()
iteradorInicio() {{ return
return Iterador<T>(cabecera);
Iterador<T>(cabecera); }}
Iterador<T>
Iterador<T> iteradorFinal()
iteradorFinal() {{ return
return Iterador<T>(cola);
Iterador<T>(cola); }}
void
void insertarInicio(T
insertarInicio(T &dato);
&dato);
void
insertarFinal(T
&dato);
void insertarFinal(T &dato);
void
void insertar(Iterador<T>
insertar(Iterador<T> &i,
&i, TT &dato);
&dato);
void
borrarInicio();
void borrarInicio();
void
void borrarFinal();
borrarFinal();
void
borrar(Iterador<T>
void borrar(Iterador<T> &i);
&i);
TT &inicio()
{
return
cabecera->dato;
&inicio() { return cabecera->dato; }}
TT &final()
&final() {{ return
return cola->dato;
cola->dato; }}

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

12

Listas circulares

Es una lista simple o doblemente enlazada donde


todos los nodos tienen puntero al siguiente
Basta con un puntero al ltimo nodo. El primer
nodo se accede como el siguiente al ltimo
til para representar:

Listas de procesos que comparten el acceso a un recurso por turno


Elementos circulares por naturaleza, como la lista de vrtices de un
polgono
ListaDCircular

cola

dato 1

dato 2

dato 3

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

13

Matrices dispersas

Una matriz dispersa es una matriz de un tamao


grande formada bsicamente por valores nulos
Aparecen en numerosos problemas de ciencia e
ingeniera
00000300000000020000000100000000
01000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000300000000000000000000000000
00200009000000000000000000000200
00000000000000000000000006000000
00000000000000000000000000000000
00100000000050000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000200
Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

14

Matrices dispersas como


listas de listas

Guardar todos los valores


bidimensional es inefciente

en

una

matriz

Una mejor implementacin guarda slo los valores


no nulos en una lista de listas
columna

fila
0000030000
0100000000
0000000000
0000000000
0000030000
0020000900
0000000000

(5, 3)

(1, 1)

(5, 3)

(2, 2)

valor

(7, 9)

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

15

Interfaz de la clase
MatrizDispersa
class
class ColMatrizDispersa
ColMatrizDispersa {{
public:
public:
int
int col;
col;
float
float val;
val;

};
};

ColMatrizDispersa(inta
ColMatrizDispersa(inta aCol,
aCol, float
float aVal)
aVal) ::
col(aCol),
col(aCol), val(aVal)
val(aVal) {}
{}

class
class FilaMatrizDispersa
FilaMatrizDispersa {{
ListaEnlazada<ColMatrizDispersa>
ListaEnlazada<ColMatrizDispersa> columnas;
columnas;
Iterador<ColMatrizDispersa>
Iterador<ColMatrizDispersa> buscar(int
buscar(int columna);
columna);
public:
public:
int
int fila;
fila;
FilaMatrizDispersa(int
FilaMatrizDispersa(int aFila):
aFila): fila(aFila),
fila(aFila), columnas()
columnas() {}
{}

};
};

float
float valor(int
valor(int columna);
columna);
void
cambiarValor(int
void cambiarValor(int columna,
columna, float
float valor);
valor);
Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

16

Interfaz de la clase
MatrizDispersa
class
class MatrizDispersa
MatrizDispersa {{
int
int maxFilas,
maxFilas, maxColumnas;
maxColumnas;
ListaEnlazada<FilaMatrizDispersa>
ListaEnlazada<FilaMatrizDispersa> filas;
filas;
Iterador<FilaMatrizDispersa>
Iterador<FilaMatrizDispersa> buscar(int
buscar(int fila);
fila);
public:
public:
MatrizDispersa(int
MatrizDispersa(int filas,
filas, int
int columnas):
columnas):
maxFilas(filas),
maxColumnas(columnas)
maxFilas(filas), maxColumnas(columnas) {}
{}
float
float valor(int
valor(int fila,
fila,
void
cambiarValor(int
void cambiarValor(int

};
};

int
int
int
int

int
int columna);
columna);
fila,
fila, int
int columna,
columna, float
float valor);
valor);

getNumFilas()
getNumFilas() {{ return
return maxFilas;
maxFilas; }}
getNumColumnas()
getNumColumnas() {{ return
return maxColumnas;
maxColumnas; }}

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

17

Implementacin de la Matriz
Dispersa
Iterador
Iterador FilaMatrizDispersa::buscar(int
FilaMatrizDispersa::buscar(int columna)
columna) {{
Iterador<ColMatrizDispersa>
Iterador<ColMatrizDispersa> ii == columnas.iterador();
columnas.iterador();
while
(i.haySiguiente()
&&
i.dato().col
while (i.haySiguiente() && i.dato().col << columna)
columna) {{
i.siguiente();
i.siguiente();
}}
return
return i;
i;
}}
float
float FilaMatrizDispersa::valor(int
FilaMatrizDispersa::valor(int columna)
columna) {{
Iterador<ColMatrizDispersa>
Iterador<ColMatrizDispersa> ii == buscar(columna);
buscar(columna);
if
if (i.haySiguiente()
(i.haySiguiente() &&
&& i.dato().col
i.dato().col ==
== columna)
columna) {{
return
return i.dato().val;
i.dato().val;
}}
}}

return
return 0;
0;

void
void FilaMatrizDispersa::cambiarValor(int
FilaMatrizDispersa::cambiarValor(int columna,
columna, float
float valor)
valor) {{
Iterador<ColMatrizDispersa>
Iterador<ColMatrizDispersa> ii == buscar(columna);
buscar(columna);

}}

if
if (i.haySiguiente()
(i.haySiguiente() &&
&& i.dato().col
i.dato().col ==
== columna)
columna) {{
i.dato().val
i.dato().val == valor;
valor;
}}
else
else {{
columnas.insertar(i,
ColMatrizDispersa(columna,
valor));
Leccin 7: Listas
doblemente enlazadas. Listas circulares y matrices
dispersas
columnas.insertar(i,
ColMatrizDispersa(columna,
valor));
}}

18

Implementacin de la Matriz
Dispersa

Iterador<FilaMatrizDispersa>
Iterador<FilaMatrizDispersa> MatrizDispersa::buscar(int
MatrizDispersa::buscar(int fila)
fila) {{
Iterador<FilaMatrizDispersa>
Iterador<FilaMatrizDispersa> ii == filas.iterador();
filas.iterador();
while
while (i.haySiguiente()
(i.haySiguiente() &&
&& i.dato().fila
i.dato().fila << fila)
fila) {{
i.siguiente();
i.siguiente();
}}
}}

return
return i;
i;

float
float MatrizDispersa::valor(int
MatrizDispersa::valor(int fila,
fila, int
int columna)
columna) {{
Iterador<FilaMatrizDispersa>
Iterador<FilaMatrizDispersa> ii == buscar(fila);
buscar(fila);
if
if (i.haySiguiente()
(i.haySiguiente() &&
&& i.dato().fila
i.dato().fila ==
== fila)
fila) {{
return
return i.dato().valor(columna);
i.dato().valor(columna);
}}
}}

return
return 0;
0;

void
void MatrizDispersa::cambiarValor(int
MatrizDispersa::cambiarValor(int fila,
fila, int
int columna,
columna, float
float
valor)
{
valor) {
Iterador<FilaMatrizDispersa>
Iterador<FilaMatrizDispersa> ii == buscar(fila);
buscar(fila);
if
if (!i.haySiguiente()
(!i.haySiguiente() ||
|| i.dato().fila
i.dato().fila !=
!= fila)
fila) {{
filas.insertar(i,
filas.insertar(i, FilaMatrizDispersa(fila));
FilaMatrizDispersa(fila));
}}
Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

}}

i.dato().cambiarValor(columna,
i.dato().cambiarValor(columna, valor);
valor);

19

Conclusiones
(listas doblemente enlazadas)

Las listas doblemente enlazadas son una estructura


de datos fexible y efciente para aplicaciones que
requieren inserciones y borrados arbitrarios
Complejas comparadas con un vector dinmico
Consumo de memoria alto al requerir dos punteros
por dato almacenado

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

20

Conclusiones
(listas circulares y mat. dispersas)

Las listas circulares son listas especializadas tiles


para ciertas aplicaciones
Las matrices dispersas pueden ser implementadas
con un consumo de memoria mnimo mediante
listas de listas que nicamente guardan los datos
relevantes

Leccin 7: Listas doblemente enlazadas. Listas circulares y matrices dispersas

21

Вам также может понравиться