Coruniversitaria, Corporación Universitaria de Ibagué
Facultad de Ingeniería de Sistemas

Estructuras de Datos II 

Inicio

Generalidades

Ejercicios

Talleres

Proyecto

Ejercicios "amistosos"

 Grafos


 Un grafo es una estructura de datos no lineal que se utiliza para representar relaciones arbitrarias, no jerárquicas, entre los elementos de un conjunto.
Consideremos las ciudades Ibagué, Bogotá, Medellín, como elementos
de un conjunto y las rutas aéreas como las relaciones existentes entre
ellas. En éste caso, las relaciones no son jerárquicas, pues es posible
que de Ibagué se pueda ir a Bogotá, de Bogotá a Medellín y de Medellín
a Ibagué.

 Si se hace una reseña histórica acerca de grafos, encontramos que EULER fue el primero en hablar del tema (año 1736), como parte de la solución del famoso problema de los puentes de Koenigsberg:
 'Por la ciudad prusiana de Koenigsberg pasa el rio Pregel, que al pasar
la ciudad tiene dos islas que están unidas a las dos riberas y entre sí
por siete puentes. La gente que pasa por los puentes se ha preguntado si saliendo de la casa es posible dar un paseo por los 7 puentes, de tal
manera que pasee por cada puente una y sólo una vez, y se regrese al
punto de partida
'.  Euler trató de resolver este problema y llegó a la
conclusión de que no es posible encontrar dicha ruta, debido a que a cada parte, isla o ribera, le llega un número impar de puentes, previo
modelamiento del problema mediante un grafo, reemplazando las islas y
riberas por puntos y los 7 puentes por segmentos.

Considere el siguiente caso
: Carlos, Andrés y David son vecinos, pero
actualmente se encuentran disgustados entre sí. Ayer recibieron la
notificación de que se les instalarán las tuberías de agua, teléfono y
gas; ellos no permiten que ningún tubo de la instalación se intercepte.
Cada uno ha intentado, por separado, resolver su problema en el papel,
reemplazando cada persona por un punto, lo mismo que los servicios, y
luego uniéndolos por medio de segmentos. Es decir, los tres han intentado dibujar el grafo planar de tal forma que no intercepten los segmentos.
¿Cuántos segmentos se pueden dibujar sin que se intercepten?
 

 DEFINICIONES Y CONCEPTOS BÁSICOS

Algoritmo de Dijkstra: Permite encontrar la ruta óptima desde un nodo a los demás nodos del grafo.

Algoritmo de Floyd: Permite encontrar la ruta óptima entre todos los pares de nodos del grafo.

Algoritmo de Warshall: Permite determinar no sólo cuál es la ruta mínima, sino el camino de mínimo costo para realizarla.

Arco o arista: Enlace entre los nodos de un grafo en el que se especifica la dirección y sentido en que hace la conexión.

Camino o cadena: Secuencia de segmentos que une dos nodos cualesquiera del grafo.

Camino simple: Es un camino en el cual ningún vértice se repite.

Camino cerrado: Camino en el que el primero y el último vértice son el  mismo.

Ciclo: Es un camino de longitud 3 o más.

Dirgrafo G(N,A): Es un grafo dirigido.

Grado: Número de arcos que entran o que salen de un nodo del grafo.

Grafo conexo: Existe un camino entre cualquier par de vértices.

Grafo dirigido G(N,A): Conjunto de nodos unidos mediante arcos.

Grafo etiquetado: Cuando a sus vértices o aristas se les ha asignado un valor de los posibles valores de un conjunto.

Grafo G(N,S): Un conjunto de nodos unidos mediante segmentos. Un segmento implica que los nodos están unidos, pero no especifica la dirección o el sentido en que se efectúa la relación.

Listas de adyacencia: Manera de representar un grafo en la que cada nodo es una cabeza de lista y con los nodos adyacentes se conforma la lista.

Matriz de adyacencia: Forma de representar la conectividad de un grafo mediante una matriz NxN, en la que en la intersección del nodo i con el nodo j hay un cero si no hay conexión en ese sentido, o 1 si la hay.

Matriz de desplazamientos: Manera de representar la conectividad de un grafo mediante una matriz NxN en la que en la intersección del nodo i con el nodo j hay un cero, o el valor o costo del desplazamiento si lo hay.

Recorrido por expansión: Método para recorrer un grafo en el que se toma como punto de partida un nodo del grafo y se visitan y marcan los nodos adyacentes del nodo, y se continúa recursivamente el recorrido por expansión.

Recorrido en profundidad: Método para recorrer un grafo en el que se toma como punto de partida un nodo del grafo y se marca como visitado, se recorre cada nodo adyacente no visitado usando el recorrido en profundidad recursivamente.
 

  Para resolver un problema de grafos utilizando el computador, debemos ser capaces de almacenar grafos en la memoria del computador. Existen diferentes estructuras de datos que permiten almacenar un grafo, entre ellas están la estructura de tipo red o malla, las listas de adyacencia y las matrices de adyacencia. 

  Para almacenar un grafo en una lista de adyacencia, se puede trabajar con un arreglo de listas. Es conveniente utilizar una lista de adyacencia cuando el grafo es disperso, es decir, aquel que tiene muchos vértices y pocos arcos o aristas.

Cuando el grafo tiene un alto número de arcos, se debe considerar la posibilidad de trabajar con una matriz de adyacencia.

------------------------------------------------------------------------------------

// El siguiente programa almacena un grafo en un arreglo de  listas de adyacencia.
#include "iostream.h"
#include "conio.h"
#define T 10
#define L clrscr()

struct nodo{
  int v;
  nodo *sig;
};

void ins_nodo(nodo g[],int v,int ad){
     nodo *p,*q,*nuevo;
     nuevo=new(nodo);
     nuevo->v=ad;
     nuevo->sig=NULL;
     q=NULL;
     p=g[v].sig;
     while(p!=NULL){
          q=p;
          p=p->sig;
     }
     if (q == NULL)
         g[v].sig=nuevo;
     else
         q->sig=nuevo;
}

leer_grafo(nodo grafo[]){
     int v,ad,n,i;
     cout << "Digite el numero de vertices: ";
     cin >> n;
     for(i=1;i<=n;i++){
         grafo[i].v=0;
         grafo[i].sig=NULL;
     }
     cout << "Lea el primer vertice. Para salir, teclee -1 : ";
     cin >> v;
     grafo[v].v=v;
     while(v != -1){
          cout << "Digite el primer adjunto al vertice "<<v<<". Para terminar,teclee -1 : ";
          cin >> ad;
          while(ad != -1){
                ins_nodo(grafo,v,ad);
                cout << "Digite otro adjunto al vertice "<<v<<". Para terminar,teclee -1 : ";
                cin >> ad;
           }
           cout <<endl<<"Lea otro vertice. Para salir, teclee -1 : ";
           cin >> v;
           if (v!= -1)
              grafo[v].v=v;
     }
     return(n);
}

void listar_grafo(nodo g[],int nv){
     int i;
     nodo *p;L;
     cout << "Lista de Adyacencia del GRAFO"<<endl<<endl;
     for(i=1;i<=nv;i++){
          cout <<g[i].v<<" ->";
          p=g[i].sig;
          while(p != NULL){
                  cout << p->v;
                  p=p->sig;
                  if (p!=NULL)
                      cout <<"->";
           }
           cout <<endl;
     }
}

void main()
{
     L;
     nodo grafo[T]; int nv;
     nv=leer_grafo(grafo);
     listar_grafo(grafo,nv);
     getch();
}

---------------------------------------------------------------------------------

 EJERCICIOS:

1. Escribir un programa para representar un grafo mediante una matriz de adyacencia.
2. Codificar en C++ los algoritmos de Dijkstra, Floyd y Warshall.
3. Escriba un programa para recorrer y visualizar un grafo por expansión y en profundidad.
4. Represente mediante un grafo de cinco nodos los principales sitios de Ibagué; los arcos serán las vias para comunicar estos sitios; en cada arco coloque el tiempo que toma para desplazarse. Aplique el algoritmo de Floyd para encontrar los desplazamientos óptimos entre esos sitios.
5. Incluya, en el problema anterior, un nodo adicional para el barrio donde Usted vive y coloque las distancias a dos de los otros sitios.  Aplique el algoritmo de Dijkstra y encuentre las rutas óptimas a partir de su casa.
.

Arriba  


Inicio | Biografía | Cursos | Para pensar... | Para reflexionar... | Para reir | Enlaces

 
Profesor Gustavo Martínez Villalobos
Email: gmartin@nevado.cui.edu.co
Facultad de Ingeniería de Sistemas, Coruniversitaria
Ibagué, Tolima, COLOMBIA