Documente Academic
Documente Profesional
Documente Cultură
ESTRUCTURAS DE DATOS
OBJETIVOS
Aprovechar la abstraccin para definir comportamiento y luego operaciones en nivel de implementacin Visualizar las posibles implementaciones de un TDA ya definido Utilizar con seguridad el concepto de puntero en implementaciones dinmicas Reconocer la importancia de usar solo el comportamiento de un TDA, y no su estado
LISTAS: DEFINICION
Una lista es
Las listas
TIPOS
LISTAS SIMPLES
Uno detrs de otro Del cual siempre se puede conocer al nodo inicial y al final
Un sucesor nico
Crear y Eliminar Conocer si esta vaca Aadir elementos y removerlos Consultar el primer y al ultimo elemento Imprimir sus elementos en pantalla Buscar un elemento con cierta informacin en la lista
Estado:
<listaSimple> ::= <comienzo> + {<ref_nodo>} + <final> <comienzo> ::= <enlace> <final> ::= <enlace>
Una lista esta compuesta de nodos, y por eso es importante definir el TDA Nodo Un nodo de una lista
Almacena informacin de cualquier tipo dentro y Es capaz de viajar o conocer otro nodo(el nodo siguiente) Crear y Eliminar Consultar y modificar la informacin que almacena Consultar y modificar el enlace que mantiene con otro nodo <nodo> <enlace> ::= <contenido> + <enlace> ::= <ref_nodo> | <ref_invalida>
Comportamiento
IMPLEMENTACION CONTIGUA
Cada nodo es realmente un elemento del arreglo Entonces, el enlace con el siguiente nodo seria simplemente el indice del siguiente elemento dentro del arreglo OJO: En este tipo de implementacin no es necesario crear el TDA Nodo
Al crearla se debe indicar el tamao mximo del arreglo Al insertar o remover un elemento,
2 3 En uso
6 7 Desperdicio
CONTIGUAS: OPERACIONES
Creacin y Eliminacin
Busqueda y Recorrido
int LSCont_BuscarNodo(LSCont L, Generico G, Generico_ComoComparar fn); bool LSCont_EsNodoDeLista(LSCont L, int i); void LSCont_Recorrer(LSCont L, Generico_ComoImprimir fn);
void LSCont_InsertarNodoInicio(LSCont *L, Generico G); void LSCont_InsertarNodoFin(LSCont *L, Generico G); Generico LSCont_SacarNodoInicio(LSCont *L); Generico LSCont_SacarNodoFin(LSCont *L);
CONTIGUAS: DECLARACION
La lista contigua
Es un arreglo de elementos de cualquier tipo realmente es un ARRAYU No olvidemos que hay que predefinir el mximo de nodos de la lista
header=0
10 5 8 25 2
last
31
MAX
Elementos
CONTIGUA: BASICAS
El ndice del ltimo elemento debe ser un ndice invlido, un valor negativo. No importara que el arreglo tenga elementos pues no sern tomados en cuenta.
last
last
-1
9
MAX-1
void LSCont_VaciarLista(LSCont *L){ L->ultimo = -1; } LSCont *LSCont_CrearLista(int max){ LSCont *nuevalista; nuevalista->Elementos = ArrayU_Crear(max, 0); nuevalista->ultimo = -1; return nuevalista; } void LSCont_EliminarLista(LSCont *L){ LSCont_VaciarLista(L); } } ArrayU_Eliminar(&(L->Elementos)); Si la lista est llena es } bool LSCont_EstaLlena(LSCont L){ return (L.ultimo == bool LSCont_EstaVacia(LSCont L){ return(L.ultimo<0);
ArrayU_Tamanio(L.Elementol)-1);
porque el ndice del ltimo ha llegado al verdadero ltimo ndice posible en el arreglo: MAX -1
CONTIGUA: BUSQUEDA
int LSCont_BuscarNodo(LSCont L, Generico G, Generico_Comparacion fn){ int i; Generico elemento; for(i = 0; i <=L.ultimo;i++){ elemento = ArrayU_ElemC(L.Elementos, i); if(f(elemento, G) == 0) return (i)
}
return(-1); }
CONTIGUA: INSERTAR
last last 9 10 0 10 1 1 1 5 2 5 8 3 8 4 5 6 7 8 9 bool LSCont_Insertar(LSCont *L, int P, Generico G){ int i, Generico ele1; if(LSCont_EstaLlena(L)) return FALSE; if(P<=-1) return FALSE; //MOVER TODOS for(i = L->ultimo; i >=P ;i--){ ele1 = ArrayU_ElemC(L->Elementos,i); ArrayU_ElemM(L->Elementos,i+1, ele1); } ArrayU_ElemM(L->Elementos, P, G); L->utlimo ++; return TRUE; }
bool LSCont_InsertarInicio(LSCont *L, Generico G){ int i; Generico ele1, ele2; //No insertar si ya esta llena if(LSCont_EstaLlena(L)) return FALSE; //Mover todo hacia delante for(i = L->ultimo; i >=0 ;i--){ ele1 = ArrayU_ElemC(L->Elementos,i); ArrayU_ElemM(L->Elementos,i+1, ele1); } ArrayU_ElemM(L->Elementos, 0, G); L->ultimo++; return(TRUE); }
9
10 0 9 1 1 1 1 5 2
last last
5 8 3 8 4 5 6 7 8 9
CONTIGUA: SACAR
bool LSCont_EliminarNodo(LSCont *L, int P){ int i; Generico ele1; if(LSCont_EstaVacia(L)) return FALSE; if(P<=-1) return FALSE //RETROCEDER TODOS for(i = P; i < L->ultimo;i++){ ele1 = ArrayU_ElemC(L->Elementos, i+1); ArrayU_ElemM(L->Elementos, i, ele1); } L->last --; return TRUE; } bool LSCont_EliminarxInfo(LSCont *L, Generico G){ int pos; if(LSCont_EstaVacia(L)) return FALSE; pos = LSCont_Localizar(L, G); if(pos >= 0) return(LSCont_EliminaNodo(L, pos);); } 4 5 6 7 8 9
Eliminar por Info, dada una cierta informacin, buscar el elemento que la tenga y eliminarlo
last last
10 0 5 1 1 8 5 2 8 3
Contenido Enlace
NODO B
C
Al insertar o eliminar un nodo ya no hay que mover al resto de elemento, solo enlazarlo con la lista
25
NODO A
25
10 5 8 25 2 2 31 31
Contenido: Datos enteros, reales, o incluso, de Estructuras: Estudiante, Auto, etc.... Y adems, el nodo tambin contiene un enlace con su nodo siguiente Este enlace, puede no enlazar el nodo con nadie, el nodo esta solito, no forma parte de ninguna lista O puede apuntar a otro nodo, indicando que ese es su siguiente, formando una Lista
Crear y Eliminar
Un contenido de cualquier tipo de dato, entero, real, estructuras, etc...... Un enlace, que es la referencia al nodo siguiente, la direccin del nodo siguiente
typedef struct TLSE_Nodo{ Generico G;
LSE_nodo *LSE_CrearNodo(Generico G) { LSE_nodo *p; p = (LSE_nodo *)malloc(sizeof(LSE_nodo)); if(p) { p->G = G; p->sig = NULL; } return p; }
En una lista hay que llevar control de las posiciones al primer y el ltimo elemento
En la lista, las posiciones son direcciones de memoria: punteros
Los elementos o Nodos van siendo creados y eliminados a medida que se va necesitando
LSE: OPERACIONES
Crear y Eliminar
LSE * LSE_CrearLista(); void LSE_Eliminar(LSE **L); LSE_nodo *LSE_NodoInicio(LSE L); LSE_nodo *LSE_NodoFin(LSE L); bool LSE_EstaVacia(LSE L); bool LSE_InsertarNodoInicio(LSE *L, LSE_nodo *pNodo); bool LSE_InsertarNodoFin(LSE *L, LSE_nodo *pNodo); bool LSE_Insertar(LSE *L, LSE_nodo *p, LSE_nodo *nuevo); LSE_nodo *LSE_SacarNodoInicio(LSE *L); LSE_nodo *LSE_SacarNodoFin(LSE *L); bool LSE_EliminarxPos(LSE *L, LSE_nodo *p);
Conocer Estado
Aadir y Remover
Busqueda y Recorrido
LSE_nodo *LSE_BuscarNodo(LSE L, Generico G, Generico_fnComparar f); bool LSE_ExisteNodo(LSE L, LSE_nodo *p); void LSE_Recorrer(LSE L, Generico_fnImprimir f);
LSE: DECLARACIN
Al crear una lista, esta estar vaca, su primero y ultimo no apuntaran a nadie
Al Eliminar una lista, cada uno de los nodos debe ser liberado
void LSE_Vaciar(LSE *L){ LSE_nodo *p; while(!LSE_EstaVacia(*L)){ p = LSE_SacarNodoFin(L); LSE_Nodo_Eliminar(p);
}
LSE *LSE_CrearLista(){ LSE *lnueva; lnueva = malloc(sizeof(LSE)); lnueva->header = lnueva->last = NULL; return lnueva; }
header last
LSE: BUSQUEDA
Encontrar el nodo con la informacin buscada o Que ya no haya mas nodos Un puntero se ubicara en el header Y luego ir avanzando al siguiente, y al siguiente y al siguiente
LSE_nodo *LSE_BuscarNodo(LSE L, Generico G, Generico_fnComparar f){ LSE_nodo *p; for(p = L.header; p!= NULL; p = LSE_Nodo_Siguiente(p)){ if(f(LSE_Nodo_Contenido(p),G) ==0) return(p); } return(NULL); }
Al encontrar al nodo buscado, no se retorna su posicin como ndice, esta no importa Se retorna la direccin de este nodo(puntero)
header 10 pp 5 p p 8 p p
Busco 25 30
last 25 p p 2 p 31 p p
LSE: ANTERIOR
La posicin Dada la direccin de un nodo(pos), esta funcin retorna la direccin del nodopanterior es la Hay que buscar desde el header de un nodo El nodo buscado es aquel cuyo siguiente es igual a pos fuera de Si el elemento buscado es el primero en la lista, no hay anterior la lista
p
LSE_nodo * LSE_Anterior(LSE L, LSE_nodo *p){ LSE_nodo *q; if(LSE_EstaVacia(L)) return NULL; if(L.header == p) return NULL; for(q=L.header; q!=NULL;q=q->sig){ if(q->sig ==p) return(q); } header return(NULL); } 10 qq 5 q q
last 2 q 31 q q
LSE: INSERTAR
La NODO en si que se va a insertar Este nodo ya debi haber sido creado antes de insertarlo Insertar al inicio o al final Insertar en medio de la lista
last->sig = nuevo;
INSERCION AL INICIO/FINAL
Si la lista esta vaca, tanto header como last apuntan al nuevo nodo Si no, si es al inicio el nuevo header, es el nuevo nodo Si no, si es al final, el nuevo last es el nuevo nodo
nuevo last 18
header nuevo
header 10 5 8 25 2
31
9 nuevo->sig = header; header = nuevo; bool LSE_InsertarNodoInicio(LSE *L, LSE_nodo *nuevo){ if (!nuevo) return FALSE; if(LSE_EstaVacia(*L)){ L->header = L->last = nuevo; } else{ LSE_Nodo_ModificarEnlace( nuevo, L->header); L->header = nuevo; } return(TRUE); } bool LSE_InsertarNodoFin(LSE *L, LSE_nodo *nuevo){ if(!nuevo) return FALSE; if(LSE_EstaVacia(*L)){ L->header = L->last = nuevo; } else{ LSE_Nodo_ModificarEnlace(L->last,, nuevo); L->last = nuevo; } return(TRUE); }
INSERTAR EN MEDIO
bool LSE_Insertar(LSE *L, LSE_nodo *p, LSE_nodo *nuevo){ if(L->last==p){//Insertar al final return(LSE_InsertarNodoFin(L, nuevo)); }else{ if(!p || ! LSE_ExisteNodo(*L,p)) return FALSE; Debe recibir la posicin donde se va a if(LSE_EstaVacia(*L)) insertar L->header = L->last = nuevo; Insertemos despus else{ LSE_Nodo_ModificarEnlace( Si Lista Vaca, el nuevo header y last, es nuevo, LSE_Nodo_Siguiente(p)); el nuevo nodo LSE_Nodo_ModificarEnlace(p, nuevo); Si la posicin no existe no efectuar la } insercin } return(TRUE); Si la lista solo tiene un elemento, el nuevo
header nuevo
18
tmp
LSE_nodo *LSE_SacarNodoInicio(LSE *L){ LSE_nodo *tmp = L->header; if(LSE_EstaVacia(*L)) return NULL; if(L->header == L->last) LSE_InicializarLista(L); else { L->header = L->header->sig; } return(tmp); }
tmp LSE_nodo *LSE_SacarNodoFin(LSE *L){ LSE_nodo *tmp=L->header; if(LSE_EstaVacia(*L)) return NULL; if(L->header == L->last) LSE_InicializarLista(L); else{ tmp = L->last; L->last = LSE_Anterior(*L, L->last); L->last->sig = NULL; } return(tmp); }
Lista no debe estar vaca La posicin enviada debe existir en la lista Revisar si se desea eliminar el header o el last
p_ant->sig = p->sig;
header 10 5
p 8 free(p); 25
bool LSE_EliminarxPos(LSE *L, LSE_nodo *p){ LSE_nodo *p_ant; if(LSE_EstaVacia(*L)) return 0; if(!p || !LSE_ExisteNodo(*L, p)) return FALSE; if(p==L->header) LSE_SacarNodoInicio(L); else if(p == L->last) LSE_SacarNodoFin(L); else{ p_ant = LSE_Anterior(*L,p); p_ant->sig = p->sig; p->sig = NULL; } return(TRUE); } last 2 31
VISUALIZAR