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)
Dada la Lista L,      InsertarNodoInicio(L, C)
la posición P y       InsertarNodoFinal(L, C)
                      InsertarNodoAntesDe(L, P, C)
la información C      Referencia_Nodo EliminarPrimero(L)
                      Referencia_Nodo EliminarUltimo(L)
                      EliminarNodo(L, P)
                      Referencia_Nodo BuscarNodo(L, C)
                      Referencia_Nodo PosAnterior(L, P)
                      Recorrer(L)
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

            header                                              last

             10        5        8          25           2       31



                                                                     Cuando la lista
                                                                       esta vacia,
D   I   D      typedef struct LDE_Nodo {
A       S                                       typedef struct {     header y last,
                  Generico G;                                         son iguales a
                  struct LDE_nodo *sig;            LDE_Nodo *header;     NULL
                  struct LDE_nodo *ant;            LDE_Nodo *last;
               } LDE_nodo         ;             }LDE;
last = nuevo

  INSERTAR NODOS                                                                                        last
                                                                                                      nuevo
                                                                             nuevo->ant = last

                     header header->ant = nuevo                                    last                     15
  header
  header
  nuevo                10         5         21          12              17          6

     15                                                                                 last->sig = nuevo
                      nuevo->sig = header

                                                        bool LDE_InsertarNodoFin (LDE *L,
  header = nuevo
                                                                        LDE_nodo *nuevo){
bool LDE_InsertarNodoInicio(LDE *L, LDE_nodo *nuevo){
                                                            if(!nuevo) return FALSE;
  if(!nuevo) return FALSE;
  if(LDE_EstaVacia(*L)) L->header = L->last = nuevo;        if(LDE_EstaVacia(&L))
  else{                                                                 L->header = L->last = nuevo;
     nuevo->sig = L->header;                                else{
     L->header->ant = nuevo;                                    nuevo->ant = L->last;
     L->header = nuevo;
                                                                L->last->sig = nuevo;
  }
                                                                L->last = Nuevo;
  return TRUE;
}                                                           }
                                                            return FALSE;
                                                        }
INSERTAR ENTRE
                       header                  p    nuevo->sig->ant = nuevolast

                         10             5      21         12      17        6


                              nuevo->ant = p                    nuevo->sig = p->sig;
                                                     15
bool LDE_InsertarNodo(LDE *L,
               LDE_nodo *p,
                                                    nuevo
               LDE_nodo *nuevo){
  if (!p || !LDE_Existe(*L,P))                        p->sig = nuevo
               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;
}
ELIMINAR NODOS
        header                   p       P->sig->ant = p->ant       last

          10          5          21          12         17          6

                 free(p);
                                          p->ant->sig = p->sig;
LDE_nodo *LDE_EliminarxPos (LDE *L, LDE_nodo *p){
  if(!p || !LDE_Existe(L,P)) return NULL;
  if(p==L->header){                          tmp = L->header;
    return(LDE_SacarNodoInicio(L));          L->header = L->header->sig;
   } else if (P==L->last){
                                             L->header->ant = NULL; LDE_nodo *LDE_EliminarxInfo(LDE *L,
    return(LDE_SacarNodoFin(L));
                                             return(tmp);                   Generico G, Generico_Comparar fn){
   }
  else {                                                                 LDE_Nodo *p ;
    p->ant->sig = p->sig;           tmp= L->last;                        if(EstaVacia(L)) return;
    p->sig->ant = p->ant;           L->last = L->last->ant;              p = LDE_Buscar(L,G, fn);
    }
                                    L->last->sig = NULL;                 if (!p) return NULL;
  return p;
}                                   return(tmp);                         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->sig                              last

               10        5          8      25   2   31
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;                       typedef LCE_nodo *LCE;
                struct LCE_nodo *sig;
     }LCE_nodo;
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;
                                                  I   D
              nuevo->sig = nuevo;                     S


              return nuevo;
          }
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);                    Busco 25
                                                                     13
            p = p->sig;
      }while(p!= L);
             p                                          p
      return(NULL);                                     p
                                                        p
 }                      p           p         pp   pp
         last->sig                                      last

             10         5          8          25   2    31
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);
     }
nuevo->sig = last->sig

INSERTAR INICIO Y FIN                                                                last

                                                                                   nuevo
last->sig                              last->sig = nuevo          last
                                                                                    10
        10        5            8        25              2          31



                                                                                            last = nuevo
bool LCE_InsertarNodoInicio(LCE *L,             bool LCE_InsertarNodoFin(LCE *L,
                LCE_nodo *nuevo ){                              LCE_Nodo *nuevo){
    if(nuevo == NULL) return FALSE;                 if(nuevo == NULL) return FALSE;
    if(LCE_EstaVacia(*L)) L = nuevo;                if(LCE_EstaVacia(L)) L = nuevo;
                                                    else{
    else{
                                                        nuevo->sigt = L->sig;
        nuevo->sig = L->sig;
                                                        L->sig = nuevo;
        L->sig = nuevo;
                                                    }
    }
                                                    L = nuevo;
    return TRUE;
                                                    return TRUE;
}                                               }
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_EliminarxPos(LCE *L,
                                      LCE_nodo *p){
                                          LCE_Nodo *elminado, *ant;
                                          if(p == NULL || !LCE_Existe(*L,p))
                                                       return NULL;        eliminado = L
                                          if(L ==L->sig){                  ant = LCE_Anterior(L,L);
LCE_Nodo * LCE_EliminarxInfo(LCE
*L,      Generico G,                          L = NULL;                    ant->sig = L->sig;
Generico_Comparacion fn){                     return(L);                  L = ant;

    LCE_Nodo *p ;                         } else if (p==L){                return(eleminado);

    if(LCE_EstaVacia(*L)) return 0;           return(LCE_SacarNodoFin(L));

    p = LCE_Buscar(*L,I,fn);              }

    if(p == NULL) return 0;               else {

    return(LCE_EliminarxPos(L,p));            ant = LCE_Anterior(*L,p);

}                                             ant->sig = p->sig;
                                              return(p);
                                          }
                                      }
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

                 10       5       8      25   2   31
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);
                        }
                   }

ED 03 2_listas especiales

  • 1.
    LISTAS ESPECIALES Estructuras de Datos
  • 2.
    LISTAS: OPERACIONES BASICAS CrearLista()   EliminarLista(L)  Referencia_Nodo ConsultarPrimero(L)  Referencia_Nodo ConsultarUltimo(L)  bool EstaVacia(L)  bool EstaLlena(L) Dada la Lista L,  InsertarNodoInicio(L, C) la posición P y  InsertarNodoFinal(L, C)  InsertarNodoAntesDe(L, P, C) la información C  Referencia_Nodo EliminarPrimero(L)  Referencia_Nodo EliminarUltimo(L)  EliminarNodo(L, P)  Referencia_Nodo BuscarNodo(L, C)  Referencia_Nodo PosAnterior(L, P)  Recorrer(L)
  • 3.
    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>>}
  • 4.
    LDE: IMPLEMENTACION header last 10 5 8 25 2 31 Cuando la lista esta vacia, D I D typedef struct LDE_Nodo { A S typedef struct { header y last, Generico G; son iguales a struct LDE_nodo *sig; LDE_Nodo *header; NULL struct LDE_nodo *ant; LDE_Nodo *last; } LDE_nodo ; }LDE;
  • 5.
    last = nuevo INSERTAR NODOS last nuevo nuevo->ant = last header header->ant = nuevo last 15 header header nuevo 10 5 21 12 17 6 15 last->sig = nuevo nuevo->sig = header bool LDE_InsertarNodoFin (LDE *L, header = nuevo LDE_nodo *nuevo){ bool LDE_InsertarNodoInicio(LDE *L, LDE_nodo *nuevo){ if(!nuevo) return FALSE; if(!nuevo) return FALSE; if(LDE_EstaVacia(*L)) L->header = L->last = nuevo; if(LDE_EstaVacia(&L)) else{ L->header = L->last = nuevo; nuevo->sig = L->header; else{ L->header->ant = nuevo; nuevo->ant = L->last; L->header = nuevo; L->last->sig = nuevo; } L->last = Nuevo; return TRUE; } } return FALSE; }
  • 6.
    INSERTAR ENTRE header p nuevo->sig->ant = nuevolast 10 5 21 12 17 6 nuevo->ant = p nuevo->sig = p->sig; 15 bool LDE_InsertarNodo(LDE *L, LDE_nodo *p, nuevo LDE_nodo *nuevo){ if (!p || !LDE_Existe(*L,P)) p->sig = nuevo 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; }
  • 7.
    ELIMINAR NODOS header p P->sig->ant = p->ant last 10 5 21 12 17 6 free(p); p->ant->sig = p->sig; LDE_nodo *LDE_EliminarxPos (LDE *L, LDE_nodo *p){ if(!p || !LDE_Existe(L,P)) return NULL; if(p==L->header){ tmp = L->header; return(LDE_SacarNodoInicio(L)); L->header = L->header->sig; } else if (P==L->last){ L->header->ant = NULL; LDE_nodo *LDE_EliminarxInfo(LDE *L, return(LDE_SacarNodoFin(L)); return(tmp); Generico G, Generico_Comparar fn){ } else { LDE_Nodo *p ; p->ant->sig = p->sig; tmp= L->last; if(EstaVacia(L)) return; p->sig->ant = p->ant; L->last = L->last->ant; p = LDE_Buscar(L,G, fn); } L->last->sig = NULL; if (!p) return NULL; return p; } return(tmp); return(LDE_EliminarxPos(L,P);) }
  • 8.
    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->sig last 10 5 8 25 2 31
  • 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; typedef LCE_nodo *LCE; struct LCE_nodo *sig; }LCE_nodo;
  • 10.
    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; I D nuevo->sig = nuevo; S return nuevo; }
  • 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); Busco 25 13 p = p->sig; }while(p!= L); p p return(NULL); p p } p p pp pp last->sig last 10 5 8 25 2 31
  • 12.
    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); }
  • 13.
    nuevo->sig = last->sig INSERTARINICIO Y FIN last nuevo last->sig last->sig = nuevo last 10 10 5 8 25 2 31 last = nuevo bool LCE_InsertarNodoInicio(LCE *L, bool LCE_InsertarNodoFin(LCE *L, LCE_nodo *nuevo ){ LCE_Nodo *nuevo){ if(nuevo == NULL) return FALSE; if(nuevo == NULL) return FALSE; if(LCE_EstaVacia(*L)) L = nuevo; if(LCE_EstaVacia(L)) L = nuevo; else{ else{ nuevo->sigt = L->sig; nuevo->sig = L->sig; L->sig = nuevo; L->sig = nuevo; } } L = nuevo; return TRUE; return TRUE; } }
  • 14.
    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; }
  • 15.
    ELIMINA LCE_Nodo *LCE_EliminarxPos(LCE *L, LCE_nodo *p){ LCE_Nodo *elminado, *ant; if(p == NULL || !LCE_Existe(*L,p)) return NULL; eliminado = L if(L ==L->sig){ ant = LCE_Anterior(L,L); LCE_Nodo * LCE_EliminarxInfo(LCE *L, Generico G, L = NULL; ant->sig = L->sig; Generico_Comparacion fn){ return(L); L = ant; LCE_Nodo *p ; } else if (p==L){ return(eleminado); if(LCE_EstaVacia(*L)) return 0; return(LCE_SacarNodoFin(L)); p = LCE_Buscar(*L,I,fn); } if(p == NULL) return 0; else { return(LCE_EliminarxPos(L,p)); ant = LCE_Anterior(*L,p); } ant->sig = p->sig; return(p); } }
  • 16.
    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 10 5 8 25 2 31
  • 17.
    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); } }