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 <lde> ::= <comienzo> + {<nodo>}+<ultimo> <comienzo> :: = <enlace> <ultimo> :: = <enlace> <enlace> ::= (<<referencia_nodo>> | NULL) <nodo> ::= <predecesor>+<contenido>+<sucesor> <predecesor> ::= <enlace> <sucesor> ::= <enlace> <  contenido  > ::= <<dato>>{<<dato>>}
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 DS DA last header 10 5 8 25 2 31
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; } nuevo->sig = header header->ant = nuevo header = nuevo nuevo->ant = last last->sig = nuevo last = nuevo 10 5 21 12 17 6 last header header nuevo 15 last 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; P->sgt->ant = nuevo; nuevo->ant = p; } return TRUE; } nuevo->sig = p->sig; p->sig = nuevo nuevo->ant = p nuevo->sig->ant = nuevo header last 10 5 21 12 17 6 p nuevo 15
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; } 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);) } 10 5 21 12 17 6 header last 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 10 5 8 2 31 25 last->sig last
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); } Busco 25 Busco 13 10 5 8 2 31 25 last->sig last p p p p p p p p p p
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) || q== 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; } nuevo->sig = last->sig last->sig = nuevo last = nuevo 10 5 8 2 31 25 last->sig last 10 nuevo last
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; 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 10 5 8 25 2 31 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); } }

LISTAS ESPECIALES

  • 1.
  • 2.
    LISTAS: OPERACIONES BASICASCrearLista() 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
  • 3.
    TDA: LISTAS DOBLEMENTEENLAZADAS 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 <lde> ::= <comienzo> + {<nodo>}+<ultimo> <comienzo> :: = <enlace> <ultimo> :: = <enlace> <enlace> ::= (<<referencia_nodo>> | NULL) <nodo> ::= <predecesor>+<contenido>+<sucesor> <predecesor> ::= <enlace> <sucesor> ::= <enlace> < contenido > ::= <<dato>>{<<dato>>}
  • 4.
    LDE: IMPLEMENTACION typedefstruct { 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 DS DA last header 10 5 8 25 2 31
  • 5.
    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; } nuevo->sig = header header->ant = nuevo header = nuevo nuevo->ant = last last->sig = nuevo last = nuevo 10 5 21 12 17 6 last header header nuevo 15 last nuevo 15 header
  • 6.
    INSERTAR ENTRE boolLDE_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; P->sgt->ant = nuevo; nuevo->ant = p; } return TRUE; } nuevo->sig = p->sig; p->sig = nuevo nuevo->ant = p nuevo->sig->ant = nuevo header last 10 5 21 12 17 6 p nuevo 15
  • 7.
    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; } 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);) } 10 5 21 12 17 6 header last p
  • 8.
    LISTAS CIRCULARES Elavance 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 10 5 8 2 31 25 last->sig last
  • 9.
    EL TDA LISTACIRCULAR 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;
  • 10.
    CREAR NODO Paracrear 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
  • 11.
    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); } Busco 25 Busco 13 10 5 8 2 31 25 last->sig last p p p p p p p p p p
  • 12.
    ANTERIOR Es buscarel anterior a un nodo dado LCE_Nodo *LCE_Anterior(LCE *L, LCE_nodo *p){ LCE_Nodo *q; if(LCE_EstaVacia(L) || q== NULL) LCE_Anterior = NULL; q = L; do{ if(q->sig == p) return(q); q = q->sig; }while(q!=L); return(NULL); }
  • 13.
    INSERTAR INICIO YFIN 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; } nuevo->sig = last->sig last->sig = nuevo last = nuevo 10 5 8 2 31 25 last->sig last 10 nuevo last
  • 14.
    INSERTAR EN MEDIObool 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; }
  • 15.
    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; return(eleminado);
  • 16.
    LISTAS CIRCULARES DOBLEMENTEENLAZADAS 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 10 5 8 25 2 31 last
  • 17.
    RECORRER LISTA Escribiruna 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); } }