Estructuras de Datos y Algoritmos de Grafos en Pascal: Complejidad e Implementación

Enviado por Andres y clasificado en Inglés

Escrito el en español con un tamaño de 6,61 KB

Complejidad Algorítmica: Ecuaciones en Recurrencia

Ecuaciones tipo sustracción y división evaluadas según el Teorema Maestro:

  • Sustracción: T(n) = a · T(n - b) + c · nk (si 0 ≤ b)
    • Solución: O(nk+1) si a = 1; O(an div b) si a > 1.
  • División: T(n) = a · T(n / b) + c · nk (si 1 ≤ b)
    • Solución:
      • O(nk) si a < bk
      • O(nk · logb a) si a = bk
      • O(nlogb a) si a > bk

Definición de Tipos de Datos para Grafos en Pascal

Representación de un grafo mediante listas de adyacencia:

TYPE
  TListaAdy = ^TNodoAdy;
  TNodoAdy = RECORD
    destino: TNodo;
    peso: real;
    sig: TListaAdy;
  END;

  TGrafo = ^TNodoGrafo;
  TNodoGrafo = RECORD
    origen: TNodo;
    adyacentes: TListaAdy;
    sig: TGrafo;
  END;

Funciones de Verificación y Propiedades de Grafos

Función EsArbol

FUNCTION EsArbol(g: TGrafo): boolean;
BEGIN
  EsArbol := EsConexo(g) AND NOT TieneCiclo(g);
END;

Función EsConexo

FUNCTION EsConexo(g: TGrafo): boolean;
VAR
  l: TLista;
  c: TConjNodos;
BEGIN
  Anchura(g, l);
  Nodos(g, c);
  IF Cardinal(c) = Longitud(l) THEN
    EsConexo := TRUE
  ELSE
    EsConexo := FALSE;
END;

Función TieneCiclo

FUNCTION TieneCiclo(g: TGrafo): boolean;
VAR
  n: TNodo;
  visitados, c: TConjNodos;
BEGIN
  IF NOT EsVacio(g) THEN
  BEGIN
    Nodos(g, c);
    Elegir(c, n);
    CrearConjVacio(visitados);
    TieneCiclo := TieneAux(g, n, n, visitados);
  END
  ELSE
    TieneCiclo := FALSE;
END;

Función TieneAux

FUNCTION TieneAux(g: TGrafo; ant, actu: TNodo; VAR visit: TConjNodos): boolean;
VAR
  c: TConjNodos;
  encont: boolean;
  n: TNodo;
BEGIN
  encont := FALSE;
  Poner(actu, visit);
  Adyacentes(g, actu, c);
  Quitar(ant, c);
  WHILE NOT EsVacio(c) AND NOT encont DO
  BEGIN
    Elegir(c, n);
    Quitar(n, c);
    IF Pertenece(n, visit) THEN
      encont := TRUE
    ELSE
      encont := TieneAux(g, actu, n, visit);
  END;
  TieneAux := encont;
END;

Función ExisteCamino

FUNCTION ExisteCamino(g: TGrafo; n1, n2: TNodo): boolean;
VAR
  l: TLista;
BEGIN
  Anchura(g, n1, l);
  ExisteCamino := Pertenece(n2, l);
END;

Recorridos y Transformaciones

Procedimiento Profundidad

PROCEDURE Profundidad(g: TGrafo; n: TNodo; VAR l: TLista);
VAR
  c: TConjNodos;
  n2: TNodo;
  p: TPila;
BEGIN
  CrearVacia(l);
  Nodos(g, c);
  Elegir(c, n);
  CrearVacia(p);
  Apilar(n, p);
  WHILE NOT EsVacia(p) DO
  BEGIN
    Cima(p, n);
    Desapilar(p);
    IF NOT Pertenece(n, l) THEN
    BEGIN
      InsertarFinal(n, l);
      Adyacentes(g, n, c);
      WHILE NOT EsVacio(c) DO
      BEGIN
        Elegir(c, n2);
        Quitar(n2, c);
        Apilar(n2, p);
      END;
    END;
  END;
END;

Procedimiento Arb2Graf

Convierte un árbol binario en un grafo dirigido:

PROCEDURE Arb2Graf(a: TArbin; VAR g: TGrafo);
VAR
  hi, hd: TArbin;
  e, r: TElem;
  arco: TArco;
BEGIN
  IF NOT EsVacio(a) THEN
  BEGIN
    Raiz(a, r);
    HI(a, hi);
    HD(a, hd);
    InsertarNodo(r, g);
    IF NOT EsVacio(hi) THEN
    BEGIN
      Raiz(hi, e);
      CrearArco(r, e, arco);
      InsertarArco(g, arco);
      Arb2Graf(hi, g);
    END;
    IF NOT EsVacio(hd) THEN
    BEGIN
      Raiz(hd, e);
      CrearArco(r, e, arco);
      InsertarArco(g, arco);
      Arb2Graf(hd, g);
    END;
  END;
END;

Operaciones de Modificación del Grafo

Procedimiento InsertarArco

PROCEDURE InsertarArco(VAR g: TGrafo; a: TArco);
VAR
  n1, n2: TNodo;
  encon: boolean;
  aux: TGrafo;
  aux2, nuevo: TListaAdy;
BEGIN
  Ex1(a, n1);
  Ex2(a, n2);
  InsertarNodo(g, n1);
  InsertarNodo(g, n2);
  aux := g;
  WHILE NOT Igual(n1, aux^.origen) DO
    aux := aux^.sig;
  encon := FALSE;
  aux2 := aux^.adyacentes;
  WHILE (aux2 <> NIL) AND NOT encon DO
  BEGIN
    IF Iguales(aux2^.destino, n2) THEN
      encon := TRUE
    ELSE
      aux2 := aux2^.sig;
  END;
  IF encon THEN
    aux2^.peso := Valor(a)
  ELSE
  BEGIN
    new(nuevo);
    Asignar(n2, nuevo^.destino);
    nuevo^.peso := Valor(a);
    nuevo^.sig := aux^.adyacentes;
    aux^.adyacentes := nuevo;
  END;
END;

Procedimiento Arcos

PROCEDURE Arcos(g: TGrafo; VAR c: TConjArcos);
VAR
  aux: TGrafo;
  aux2: TListaAdy;
  a: TArco;
BEGIN
  CrearVacio(c);
  aux := g;
  WHILE aux <> NIL DO
  BEGIN
    aux2 := aux^.adyacentes;
    WHILE aux2 <> NIL DO
    BEGIN
      CrearArco(aux^.origen, aux2^.destino, aux2^.peso, a);
      Poner(a, c);
      aux2 := aux2^.sig;
    END;
    aux := aux^.sig;
  END;
END;

Procedimiento BorrarNodo

PROCEDURE BorrarNodo(VAR g: TGrafo; n: TNodo);
VAR
  c: TConjArcos;
  n1, n2: TNodo;
  arco: TArco;
  ant, exp: TGrafo;
  encon: boolean;
BEGIN
  Arcos(g, c);
  WHILE NOT EsVacio(c) DO
  BEGIN
    Elegir(c, arco);
    Quitar(arco, c);
    Ex1(arco, n1);
    Ex2(arco, n2);
    IF Igual(n1, n) OR Igual(n2, n) THEN
      BorrarArco(g, arco);
  END;
  exp := g;
  ant := NIL;
  encon := FALSE;
  WHILE (exp <> NIL) AND NOT encon DO
  BEGIN
    IF Igual(n, exp^.origen) THEN
      encon := TRUE
    ELSE
    BEGIN
      ant := exp;
      exp := exp^.sig;
    END;
  END;
  IF encon THEN
  BEGIN
    IF ant = NIL THEN
      g := g^.sig
    ELSE
      ant^.sig := exp^.sig;
    dispose(exp);
  END;
END;

Procedimiento BorrarArco

PROCEDURE BorrarArco(VAR g: TGrafo; a: TArco);
VAR
  n1, n2: TNodo;
  aux: TGrafo;
  encon: boolean;
  exp, ant: TListaAdy;
BEGIN
  Ex1(a, n1);
  Ex2(a, n2);
  aux := g;
  encon := FALSE;
  WHILE (aux <> NIL) AND NOT encon DO
  BEGIN
    IF Igual(aux^.origen, n1) THEN
      encon := TRUE
    ELSE
      aux := aux^.sig;
  END;
  IF encon THEN
  BEGIN
    encon := FALSE;
    exp := aux^.adyacentes;
    ant := NIL;
    WHILE (exp <> NIL) AND NOT encon DO
    BEGIN
      IF Igual(n2, exp^.destino) THEN
        encon := TRUE
      ELSE
      BEGIN
        ant := exp;
        exp := exp^.sig;
      END;
    END;
    IF encon THEN
    BEGIN
      IF ant = NIL THEN
        aux^.adyacentes := exp^.sig
      ELSE
        ant^.sig := exp^.sig;
      dispose(exp);
    END;
  END;
END;

Entradas relacionadas: