domingo, 1 de diciembre de 2013

Grafos


     Definición: Estructura de datos no lineales, conjunto de puntos llamados nodos o vértices a través de un conjunto de líneas llamadas aristas o arcos.  

       Utilidad: Relaciones múltiples en estructuras compuestas por puntos (redes principalmente).

     Aplicaciones: redes informáticas, redes de obras civiles (luz, teléfono, alcantarillado, acueducto, etc.).

     Terminología:
Figura numero 29
En figura Número 29 se muestra gráficamente un grafo lo cual lo conforman:
·        
   











d    Adyacencia: cunado nodos se comunican a través de una sola arista.
Orden: cantidad de nodos.
Camino: conjunto de aristas que comunican dos nodos.

Tipos de Grafos

  • Dirigido: las aristas tienen dirección o sentido.
  • Ponderado: las aristas tienen peso o valor.
  • Conexo: siempre existe un camino que puede comunicar dos nodos.


En la Figura numero 29  el grafo es, no dirigido, no ponderado, conexo.

Ejemplo: 
Figura numero 30
En la Figura numero 30  es un tipo de grafos, no conexo, no dirigido, penderado.

1     Implementación

        Las implementaciones se realizan con el grafo de la figura numero 29.

Arreglos (Matrices): La implementación mediante matrices se realiza de la siguiente manera:



La implementacion mediante matrices se realiza colocando en el espacio de la posición tanto vertical y horizontal el valor de cero en caso de que no exista camino entre esas dos posiciones, y uno en caso de que exista un camino entre esas dos posiciones.



Multilistas: (vector de listas): la implementacion mediante multilistas es el siguiente:




Recorridos:

Profundidad (pilas):   



Amplitud (Colas):




Algoritmos:

Dijkstra.
Kruskal.
Prim
Warshaw


Apreciaciones importantes:
La implementacion de estos algoritmos son realizados en grafos ponderados.













Métodos de Ordenamientos

Método de burbuja


En este método el elemento cuyo valor es mayor va posición a posición hacia el final  de la lista, se basa en el principio  de comparar pares de elementos adyacentes e intercambiarlos entre si hasta que estén todos en orden, El algoritmo de este método es el siguiente:



En la preparación para la exposición aprendí que el método de ordenamiento directo (burbuja) está constituido por dos estructuras repetitivas for  y una condición la cual se encarga de preguntar  si un valor que se encuentra en el arreglo en la posición actual es mayor que el de la siguiente posición.


Método de Burbuja con señal


Mediante una bandera/indicador  o bien un variable lógica, se puede detectar la presencia o ausencia  de una condición. Así, mediante  la variable BANDERA  se representa clasificación terminada  con un valor verdadero, y clasificación no terminada con un valor falso.  El algoritmo para el método es el siguiente:



Método de Ordenamiento por Inserción directa.

Consiste en hacer varias pasadas por el array, analizando en cada una de estas un elemento y se intenta encontrar su orden relativo entre los analizados en pasadas anteriores. Cada elemento se desplaza por esa lista para encontrar su lugar, cuando todos los elementos del array han sido analizados, la lista está completamente ordenada. 

El algoritmo del método es el siguiente:



Mergesort (Ordenamiento por mezcla)

Se basa en la técnica de divide y vencerás, primordial mente se divide la lista en dos listas más pequeñas de aproximadamente el mismo tamaño,  y luego utilizar mergesort recursivamente en los problemas  hasta que no se pueda subdividir más, luego se mezclan ambas mitades ordenando los datos a medida que se combinan. El algoritmo para este método es el siguiente:

Consta de dos partes primero se divide la lista.





Ordenamiento con el método de shell

Es el método de clasificación por inserción, cada elemento se compara con los elementos contiguos de su izquierda, uno tras otro. Si el elemento a insertar es más pequeño hay que ejecutar muchas comparaciones antes de colocarlo en su lugar definitivo. Shell modifico los saltos contiguos resultantes de las comparaciones por saltos de mayor tamaño y con eso se consigue la clasificación más rápida. El método se basa en fijar el tamaño de los saltos constantes, pero de más de una posición. 

Ordenación por el método de la sacudida (Shaker Sort)

 Este método de sacudida es una optimización del método de intercambio directo o burbuja.  En este algoritmo cada pasada tiene dos etapas.
Primera Pasada
Primera etapa, de derecha a izquierda: se trasladan los elementos más pequeños hacia la parte izquierda del arreglo, almacenando en una variable la posición del último elemento intercambiado.
Segunda Pasada
De izquierda a derecha: se trasladan los elementos más grandes hacia la parte derecha del arreglo, almacenando en otra variable la posición del último elemento intercambiado.

Ordenamiento por selección directa.

Este algoritmo se basa en hacer comparaciones, así que para que realice su trabajo de ordenación son imprescindibles dos cosas: un array o estructura similar de elementos comparables y un criterio claro de comparación, tal que dados dos elementos nos diga si están en orden o no.
Las funcionalidades del método de ordenamiento por selección son las siguientes:
Buscar el mínimo elemento de la lista, intercambiarlo con el primero, buscar el mínimo en el resto de la lista, intercambiarlo con el segundo, y en general buscar el mínimo elemento entre una posición i y el final de la lista, intercambiar el mínimo con el elemento de la posición i.

Método de transformación de claves.

Este método es una técnica que permite que un registro se recupere directamente con un mínimo de comparaciones o sin ellas. Esto se lleva a cabo reservando una posición en la tabla para cada posible valor de clave, de tal manera que todas las posiciones queden incluidas de acuerdo al valor de la clave. Un registro se recupera simplemente usando la clave, o una función de la clave.

Método HeapSort

Es un algoritmo de ordenación no recursivo, no estable, con complejidad computacional. Este algoritmo consiste en almacenar todos los elementos del vector a ordenar en un árbol (heap), y luego extraer el nodo que queda como nodo raíz del árbol (cima) en sucesivas iteraciones obtenido el conjunto ordenado. Basa su funcionamiento en una propiedad de los árboles, por la cual, la cima contiene siempre el menor elemento (o el mayor. Según se haya definido el árbol de todos los almacenados en el).
El método heap sort consiste esencialmente en:
Convierte el arreglo en un heap, construir un arreglo ordenado de atrás hacia adelante (mayor a menor) , sacar el valor máximo en el heap, poner el valor en el arreglo ordenado, reconstruir el heap con un elemento menos, utilizar el mismo arreglo para el heap y el arreglo ordenado.





Arboles Binarios de Búsqueda Balanceada (AVL).

Los ABB solo mantienen eficiencia en el proceso de busqueda si estan balanceados, pero cunado tienen una tendencia degenerada la eficiencia en el proceso de busqueda baja. El algoritmo AVL propone chequear en cada operacion de insercion o eliminacion el balance del arbol y reestructurarlo en caso de que este se pierda.

Figura numero 27


    Factor de Equilibrio (FE)
    Altura sub arbiol izquierdo (hsi)
    Altura sub arbol derecho (hsd)

   FE=hsi-hsd

Figura numero 28


Un arbol binario esta balanceado (AVL) para todos los nodos, si (FE>-2 y FE<2)  sino arbol no balanceado.

Después de analizar pude concluir que un árbol es perfectamente balanceado cuando es completo, también que el factor de equilibrio (FE) de una hoja es igual a cero. 

Operación

Insertar: inicialmente se aplica la misma regla ABB pero adicional mente se calcula el FE en los nodos de la rama de la inserción, comenzando por el nodo insertado, si camino a la raíz un nodo a parte de la hoja tiene FE igual a cero o se llega a la raíz y ningún FE esta fuera de rango de balance, se para el proceso porque todo esta bien; si no cuando el FE esta fuera de balance, se reestructura el árbol en un proceso llamado rotación que compromete tres nodos principalmente y puede ser de varios casos.

  • Caso 1: Rotacion(II)= izquierda izquierda, insertar: C,B,A 

  • Caso 2: Rotacion (DD)= derecha derecha, insertar: A,B,C

  • Caso 3: Rotacion (ID)= Izquierda derecha, insertar: C,A,B

  • Caso 4: Rotaciozquierda, insertar: A,C,B

    Eliminar: se aplica inicialmente la misma regla ABB, pero adicional mente se calcula el FE en la rama de la eliminación, si se detecta desbalance, se reestructura el árbol dependiendo del caso de rotación. Ejemplo: eliminar 53,33,12,7, en el siguiente árbol.

Solución:

Como el que se quiere eliminar es el 53 se suprime y luego se calcula el factor de equilibrio en la rama donde se elimino.

ay que reestructurar, escogiendo los tres nodos donde esta el problema. 
Reestructurando queda de la siguiente manera:


Eliminando el 33 resulta de la siguiente manera:


Eliminando el 12 resulta de la siguiente manera:


Eliminando el 7 resulta de la siguiente manera:
Resulta necesario reestructurar el subarbol derecho. 

El árbol resulta de la siguiente manera:


Apreciaciones importante y reflexión:

En figura numero 27 observamos gráficamente la reestructuracion de un árbol para que pueda quedar balanceado.

Puedo llegar a la conclusión que para que un árbol este balanceado debe existir una diferencia de un 1 nivel  entre el subarbol izquierdo  y el derecho. 

Se puede observar en la figura numero 28 un árbol en el cual se le calcula el factor de equilibrio a cada nodo, y la altura del subarbol izquierdo y derecho. 

Criterio para crear Arboles Binarios de búsqueda (ABB).

Para todos los nodos, los valores de las claves en el sub arbol izquierdo son menores y en el sub arbol derecho son mayores.

Ejemplo, crear un árbol a partir de las claves: 15, 18,34,9,7,8,5,3,4,22,39,16,19

Figura numero 26
Operaciones

1. Buscar: compara la clave buscada iniciando por la raiz, si no es igual preguntar si es mayor, si es asi se desplaza a la derecha, si no a la izquierda, el proceso se repite hasta encontrar coincidencia o hasta encontrar null.

2. Insertar: se busca la clave, en caso de ser encontrada, se analiza el caso, que puede ser de la siguiente manera
  • si es una hoja: simplemente se suprime 
  • si es un nodo con un sub arbol, se reemplaza por su descendiente inmediato.
  • si es un nodo con dos sub arbol, se reemplaza con el nodo mas a la derecha del sub arbol izquierdo o con el nodo mas a la izquierda del sub arbol derecho. 
Ejemplo: Insertar las claves: 24,33,70,44,57,28,12,19,

en el árbol a continuación.

Figura numero 27


Resolviendo el ejercicio queda la solución de la siguiente manera:
En este caso se inserta el 33 como hijo derecho del 27 porque como he aprendido que se inserta el nodo mayor al lado derecho. 

Se inserta el 24 como hijo izquierdo del 27 porque como he aprendido se inserta del lado izquierdo el dato menor, entonces como 24 es menor que el 27, se inserta la lado izquierdo.
Como el 70 es mayor que el 39 osea la raiz se lleva a insertar del lado derecho,  se añaliza con el 50 y se lleva a insertar del lado derecho ya que es mayor, se analiza con el 67 y tambien miramos que es mayor lo cual se inserta del lado derecho del 67. 



Eliminar las claves: 19, 44, 57, del árbol que resulto al insertar las claves anteriores.


eliminado el 19 queda de la siguiente manera.
Como el 19 era una hoja simplemente se suprime como lo aprendido anteriormente.
Eliminado el 44 resulta el árbol de la siguiente manera:

El 44 como también era una hoja simplemente se suprime.

   Eliminado el 57 resulta el árbol de la siguiente manera:






Apreciaciones Importantes y reflexión.

Analizando el criterio para crear arboles binarios de búsqueda ABB pude llegar a concluir que al momento de recorrer el árbol en inorden resultan los datos en forma ordenada.

Recorrido de un árbol binario.

Recorrido en Pre-Orden:
Visitar la Raíz.
Recorrer el subArbol izquierdo.
Recorrer el subArbol derecho.

Recorrido en In-Orden
Recorrer el subArbol izquierdo.
visitar la raíz.
Recorrer el subArbol derecho. 

Recorrido en Pos-Orden
Recorrer el subArbol izquierdo.
Recorrer el subArbol derecho.
visitar la raíz.


Figura numero 18

Los   recorridos del árbol ilustrado en la figura numero 18 en:
preOrden:  abdcef. 
inOrden: dbaecf.
posOrden: dbefca.

En la clase aparte de aprender los diferentes recorridos pude mirar con la practica realizado en el ejemplo anterior con la fugura numero 18 la manera en la cual se recorren estos arboles.

Funciones de Recorrido


Figura numero 19



Figura numero 20



Figura numero 21

Como Funciona la Función.

Figura numero 22
Se tiene el siguiente Árbol Binario:


Como ya sabemos que estas funciones son recursivas,  pasaremos a explicar mediante la pila del sistema operativo la cual en una función de autollamado guarda las instrucciones que quedan pendientes por realizar, el recorrido en pre orden del árbol mostrado en la figura numero 22 es:

  • La primera instrucción del método preOrden es mostrar el dato en el cual se esta apuntando actualmente en este caso lo primero en realizar es imprimir la letra A ya que la variable raíz actualmente apunta a ese objeto.
  • Se sigue con la siguiente instrucción la cual es el llamado a la función pero con la referencia del objeto que se encuentra a su izquierda, y en la pila del sistema operativo queda almacenada la instrucción siguiente que es otro autollamado con la  dirección del objeto que se encuentra a la izquierda, en la figura numero 23 se muestran las instrucción que van quedando por realizar en los diferentes autollamados que se realizan en la función.


Figura Numero 23

Resultado del árbol en pre orden: A B D C E F

Se logro tener mas destreza para la realización de un método recursivo y como es el funcionamiento de este, lograre tener aun mas mirando el funcionamiento de los demás métodos.  

Arboles de Expresión

Árbol binario completo para representar y evaluar expresiones aritméticas, sus hojas son los operando y el resto de nodo sus operadores.

Expresión: a+b*c

Posibles Arboles:

Figura Numero 24

Arbol
Correcto
A
      x
B
      x
C                      
   ü   
D
       x
E
       x

Criterios para crear arboles de Expresión

Expresión: a+b*c
                String posfija: abc*+

             

Figura numero 25

Como aprendimos que para crear un árbol de expresión los nodos raíces del arbol o subarbol  son los operadores, entoces el tipo de recorrido de estos arboles es de tipo posOrden en caso de que se quiera mostrar la expresión en postija.

Apreciaciones Importantes:

En la figura numero 24 el árbol C es de expresión porque  es completo y sus hojas son los operando y el resto sus operadores como lo aprendido anteriormente.

En la Figura numero 25 se muestra como se lleva el proceso para crear arboles de expresión mediante una pila de tipo NodoArbolBin en la cual se almacenan los operando y al encontrar un operador se saca de la pila dos operando y se crea un subárbol, así hasta terminar de crear el árbol.


Árbol Binario de Búsqueda (ABB)

Proponen un algoritmo que genera una estructura ordenada y hace mas eficiente el proceso de busqueda que las otras estructuras vistas con anterioridad.

Eficiencia: Menor numero de comparaciones al buscar un elemento.
Por cada avance se descarta un 50% de los elementos.

sábado, 2 de noviembre de 2013

Arboles Binarios.


1. Definición: Arboles que tienen máximo dos hijos por nodo.

2. Terminología: máximo dos hijos que se distingue entre izquierdo y derecho.

Figura numero 15

  • Completo: todos los nodos o tienen dos hijos o cero.
  • Lleno: todos los niveles tienen el máximo de nodos y se calcula por medio de la formula 2^n -1. donde n es altura.
  • Degenerado: todos los nodos solo tienen un hijo excepto la hoja.
  • Balanceado: en todos los nodos la diferencia entre las alturas del subárbol   izquierdo y derecho es menor que 2 y mayor que -2. 


  Ejemplos:

Se tienen los siguientes Arboles:



Árbol
A
B
C
D
Completo
x
x
ü   
ü   
Lleno
x
x
x
ü   
Degenerado
x
ü   
x
ü   
Balanceado
ü   
x
ü   
ü   
Después de analizar pude concluir que todo árbol binario que sea lleno es por consiguiente completo, pero todo árbol completo no necesariamente tiene que ser lleno.  


3. Implementacion
  
        3.1 Estática (Arreglos)
              
           
Figura numero 16

En la imagen se ilustra un árbol el cual es implementado con arreglos, resulta necesario declarar tres arreglos el primero es de tipo T que guardara los datos que tiene el árbol, el segundo es de tipo int que almacena la posición en que están almacenados los datos que se encuentran en el árbol  del  lado izquierdo, el tercero también cumple la función del segundo pero en este se guardan los del lado derecho.


  3.2 Dinámica (Nodos)

  
Figura numero 17


   En esta imagen se muestra el árbol que aparece en la figura numero 16 con la implementacion en nodos donde se declara una variable raíz el cual apunta al primero nodo del árbol.

Clase NodoArbolBin.

public class NodoArbolBin <T> {

private T dato;
private NodoArbolBin izq;
private NodoArbolBin der;

public NodoArbolBin (T dato){
this.dato=dato;
izq=der=null;
}

public NodoArbolBin(T dato, NodoArbolBin izq, NodoArbolBin der){
  
  this.dato=dato;
   this.izq=izq;
   this.der=der;
}

public T getDato(){ return dato;}
public NodoArbolBin getIzq() { return izq;}
public NodoArbolBin getDer(){ return der;}
public void setIzq(NodoArbolBin izq){
this.izq=izq;
}
public void setDer(NodoArbolBin der){
this.der=der;
}
}

public class Principal {
  public static void main (String ae []){
  NodoArbolBin raiz= new NodoArbolBin ("A");
  raiz.setIzq(new NodoArbolBin("B"));
  raiz.setDer(new NodoArbolBin("C"));
 NodoArbolBin p = raiz.getIzq();
p.setIzq(new NodoArbolBin("D"));
p= raiz.getDer();
p.setIzq(new NodoArbolBin("E"));
p.setDer(new NodoArbolBin("F"));
preOrden(raiz);
}

public static void preOrden(NodoArbolBin r){
  if(r!=null){
 System.out.println(r.getDato());
   preOrden(r.getIzq());
  preOrden(r.getDer());
}
}
}


 Apreciaciones Importantes y Reflexión.

En la figura numero 16 los arreglos izq y der donde aparecen el -1 quiere decir que no tiene hijos de ese lado ya sea tanto izquierdo como derecho.

En la figura numero 17 el árbol realizado con nodos cuando en la parte izq o der tenga almacenado un null quiere decir que no tiene hijos de ese lado.  

Logre aprender sobre otra clase de árbol  sus terminologias y sus  implementaciones, con base a las gráficas se paso a realizar la clase NodoArbolBin.

Una conclusión muy importante es que todo árbol degenerado solo tiene un hijo.