LISTAS ESPECIALES Estructuras de Datos
LISTAS: OPERACIONES BASICAS CrearLista() EliminarLista(L) Referencia_Nodo ConsultarPrimero(L) Referencia_Nodo ConsultarUltimo(L) bool EstaVacia(L) bool EstaLlena(L) InsertarNodoInicio(L, C) InsertarNodoFinal(L, C) InsertarNodoAntesDe(L, P, C) Referencia_Nodo EliminarPrimero(L) Referencia_Nodo EliminarUltimo(L) EliminarNodo(L, P) Referencia_Nodo BuscarNodo(L, C) Referencia_Nodo PosAnterior(L, P) Recorrer(L) Dada la Lista L, la posición P y la información C
TDA: LISTAS DOBLEMENTE ENLAZADAS En las listas enlazadas solo se avanza en un sentido En las doblemente, se puede avanzar hacia la derecha o hacia la izq. En estas listas cada nodo tiene Un predecesor, excepto el primero Un sucesor, excepto el ultimo Cada nodo ya no tiene un solo enlace, tiene dos, hacia el siguiente y hacia el anterior ::= + { }+ :: = ::= ( > | NULL) ::= + + ::= ::= >{ >}
LDE: IMPLEMENTACION typedef struct { LDE_Nodo *header; LDE_Nodo *last; }LDE; typedef struct LDE_Nodo { Generico G; struct LDE_nodo *sig; struct LDE_nodo *ant; } LDE_nodo ; Cuando la lista esta vacia, header y last, son iguales a NULL I DSDA lastheader
INSERTAR NODOS bool LDE_InsertarNodoInicio (LDE *L, LDE_nodo *nuevo){ if(!nuevo) return FALSE; if(LDE_EstaVacia(*L)) L->header = L->last = nuevo; else{ nuevo->sig = L->header; L->header->ant = nuevo; L->header = nuevo; } return TRUE; } bool LDE_InsertarNodoFin (LDE *L, LDE_nodo *nuevo){ if(!nuevo) return FALSE; if(LDE_EstaVacia(&L)) L->header = L->last = nuevo; else{ nuevo->ant = L->last; L->last->sig = nuevo; L->last = Nuevo; } return FALSE; } last header nuevo->sig = header header->ant = nuevo header header = nuevo nuevo 15 nuevo->ant = last last->sig = nuevo last last = nuevo nuevo 15 header
INSERTAR ENTRE bool LDE_InsertarNodo(LDE *L, LDE_nodo *p, LDE_nodo *nuevo){ if (!p || !LDE_Existe(*L,P)) return FALSE; if(LDE_EstaVacia(*L) || p==L->last) LDE_InsertarNodoFin(L,nuevo); else { if(!nuevo) return FALSE; nuevo->sgt = p->sgt; p->sgt = nuevo; nuevo->sgt->ant = nuevo; nuevo->ant = p; } return TRUE; } headerlast p nuevo 15 nuevo->sig = p->sig; p->sig = nuevo nuevo->ant = p nuevo->sig->ant = nuevo
ELIMINAR NODOS LDE_nodo * LDE_EliminarxPos (LDE *L, LDE_nodo *p){ if(!p || !LDE_Existe(L,P)) return NULL; if(p==L->header){ return(LDE_SacarNodoInicio(L)); } else if (P==L->last){ return(LDE_SacarNodoFin(L)); } else { p->ant->sig = p->sig; p->sig->ant = p->ant; } return p; } headerlast p p->ant->sig = p->sig; P->sig->ant = p->ant free(p); tmp = L->header; L->header = L->header->sig; L->header->ant = NULL; return(tmp); tmp= L->last; L->last = L->last->ant; L->last->sig = NULL; return(tmp); LDE_nodo *LDE_EliminarxInfo(LDE *L, Generico G, Generico_Comparar fn){ LDE_Nodo *p ; if(EstaVacia(L)) return; p = LDE_Buscar(L,G, fn); if (!p) return NULL; return(LDE_EliminarxPos(L,P);) }
LISTAS CIRCULARES El avance en las listas enlazadas es Solo a la derecha(siguiente) Limitado hasta el ultimo nodo Hay ocasiones en las que se desearia, Poder avanzar ilimitadamente Del ultimo nodo, pasar al primero last->siguiente = header last->siglast
EL TDA LISTA CIRCULAR No es necesario mantener un control de: Primero y ultimo Solo con el ultimo ya se tiene todo, pues last ->siguiente es igual a header typedef struct LCE_nodo { Generico G; struct LCE_nodo *sig; }LCE_nodo; typedef LCE_nodo *LCE;
CREAR NODO Para crear un nodo valido LCE_Nodo * LCE_Nodo_Crear(Generico G){ LCE_Nodo *nuevo; nuevo = malloc(sizeof(LCE_Nodo)); nuevo->G = G; nuevo->sig = nuevo; return nuevo; } I DS
LOCALIZA LCE_nodo *LC_Buscar(LCE *L, Generico G, Generico_Comparar fn){ LCE_nodo *p; if(LCE_EstaVacia(*L)) return NULL; p = L; do{ if(fn(p->G, G) == 0) return(p); p = p->sig; }while(p!= L); return(NULL); } last->siglast Busco 25 p pp Busco 13 p pppp pp
ANTERIOR Es buscar el anterior a un nodo dado LCE_Nodo *LCE_Anterior(LCE *L, LCE_nodo *p){ LCE_Nodo *q; if(LCE_EstaVacia(L) || p== NULL) LCE_Anterior = NULL; q = L; do{ if(q->sig == p) return(q); q = q->sig; }while(q!=L); return(NULL); }
INSERTAR INICIO Y FIN bool LCE_InsertarNodoInicio(LCE *L, LCE_nodo *nuevo ){ if(nuevo == NULL) return FALSE; if(LCE_EstaVacia(*L)) L = nuevo; else{ nuevo->sig = L->sig; L->sig = nuevo; } return TRUE; } bool LCE_InsertarNodoFin(LCE *L, LCE_Nodo *nuevo){ if(nuevo == NULL) return FALSE; if(LCE_EstaVacia(L)) L = nuevo; else{ nuevo->sigt = L->sig; L->sig = nuevo; } L = nuevo; return TRUE; } last->siglast nuevo->sig = last->sig 10 nuevo last->sig = nuevo last last = nuevo
INSERTAR EN MEDIO bool LCE_Insertar(LCE *L, LCE_Nodo *P, LCE_Nodo *nuevo){ if(P == NULL || !LCE_Existe(*L,P)) return FALSE; if(LCE_EstaVacia(*L) || p==L) LCE_InsertarNodoFin(L,nuevo); else { nuevo->sig = P->sig; P->sig = Nuevo; } return TRUE; }
ELIMINA LCE_Nodo * LCE_EliminarxInfo(LCE *L, Generico G, Generico_Comparacion fn){ LCE_Nodo *p ; if(LCE_EstaVacia(*L)) return 0; p = LCE_Buscar(*L,I,fn); if(p == NULL) return 0; return(LCE_EliminarxPos(L,p)); } LCE_Nodo *LCE_EliminarxPos(LCE *L, LCE_nodo *p){ LCE_Nodo *elminado, *ant; if(p == NULL || !LCE_Existe(*L,p)) return NULL; if(L ==L->sig){ L = NULL; return(L); } else if (p==L){ return(LCE_SacarNodoFin(L)); } else { ant = LCE_Anterior(*L,p); ant->sig = p->sig; return(p); } eliminado = L ant = LCE_Anterior(L,L); ant->sig = L->sig; L = ant; return(eleminado);
LISTAS CIRCULARES DOBLEMENTE ENLAZADAS Es una implementacion de listas circulares Con nodos que tienen dos punteros Asi se recorre la lista en el Sentido del avance del reloj y En sentido contrario Seguimos llevando un control solo del ultimo nodo de la lista last
RECORRER LISTA Escribir una operación Recorre_R que recorre una lista cir. Dobl. Enla. Hacia atras void LCDE_Recorre_R(LCDE L, Generico_Imprimir fn){ LCDE_nodo *pos; if(!LCDE_EstaVacia(L)) return; pos = L; while(TRUE){ pos = pos->ant; if(pos == L) break; fn(pos->G); }