miércoles, 30 de noviembre de 2011

Ordenamiento Radix

En informática, el ordenamiento Radix (radix sort en inglés) es un algoritmo de ordenamiento que ordena enteros procesando sus dígitos de forma individual. Como los enteros pueden representar cadenas de caracteres (por ejemplo, nombres o fechas) y, especialmente, números en punto flotante especialmente formateados, radix sort no está limitado sólo a los enteros.

Descripción

La mayor parte de los ordenadores digitales representan internamente todos sus datos como representaciones electrónicas de números binarios, por lo que procesar los dígitos de las representaciones de enteros por representaciones de grupos de dígitos binarios es lo más conveniente. Existen dos clasificaciones de radix sort: el de dígito menos significativo (LSD) y el de dígito más significativo (MSD). Radix sort LSD procesa las representaciones de enteros empezando por el dígito menos significativo y moviéndose hacia el dígito más significativo. Radix sort MSDtrabaja en sentido contrario.
Las representaciones de enteros que son procesadas por los algoritmos de ordenamiento se les llama a menudo "claves", que pueden existir por sí mismas o asociadas a otros datos. Radix sort LSD usa típicamente el siguiente orden: claves cortas aparecen antes que las claves largas, y claves de la misma longitud son ordenadas de forma léxica. Esto coincide con el orden normal de las representaciones de enteros, como la secuencia "1, 2, 3, 4, 5, 6, 7, 8, 9, 10". Radix sorts MSD usa orden léxico, que es ideal para la ordenación de cadenas de caracteres, como las palabras o representaciones de enteros de longitud fija. Una secuencia como "b, c, d, e, f, g, h, i, j, ba" será ordenada léxicamente como "b, ba, c, d, e, f, g, h, i, j". Si se usa orden léxico para ordenar representaciones de enteros de longitud variable, entonces la ordenación de las representaciones de los números del 1 al 10 será "1, 10, 2, 3, 4, 5, 6, 7, 8, 9", como si las claves más cortas estuvieran justificadas a la izquierda y rellenadas a la derecha con espacios en blanco, para hacerlas tan largas como la clave más larga, para el propósito de este ordenamiento.

Ejemplo

Vector original:
25 57 48 37 12 92 86 33
Asignamos los elementos en colas basadas en el dígito menos significativo de cada uno de ellos.
0:
1:
2:12 92
3:33
4:
5:25
6:86
7:57 37
8:48
9:
Después de la primera pasada, la ordenación queda:
12 92 33 25 86 57 37 48
Colas basadas en el dígito más significativo.
0:
1:12
2:25
3:337
4:48
5:57
6:
7:
8:86
9:92
Lista ordenada:
12 25 33 37 48 57 86 92

miércoles, 16 de noviembre de 2011

Grafos
Un grafo G es una pareja G=(V,A), donde V es un conjunto finito (i.e vértices) y A es un subconjunto del conjunto de parejas no ordenadas de V (i.e arcos). Por ejemplo G=({a,b,c},{{a,c},{c,b}}), que se representa gráficamente en la figura 1.1.


Figure 1.1: Ejemplo de grafo




Dado un grafo G con V(G) denotamos el conjunto de vértices y con A(G) denotamos el conjunto de arcos. Decimos que un arco {x,y}ΠA(Gune los vértices x ey; así que x,y denota el mismo arco que {y,x}. Si {x,y} es un arco, decimos que x e y son extremos del arco, también decimos que x es adyacente o vecino de y.

Un grafo G'=(V',A') es subgrafo de G=(V,A) si V'Ì V y AÌ A'. En tal caso escribimos G'Ì G.

Si G' contiene todos los arcos de G que unen dos vértices de V' decimos que G' es un subgrafo inducido por V' y se denota por G[V'].

El orden de un grafo G es el número de vértices, también se denota por G 1. El tamaño de G es el número de arcos, y se denota por a(G).

Decimos que dos grafos son isomorfos si hay una correspondencia entre sus conjuntos de vértices que preserva la adyacencia. Así que G=(V,E) es isomorfo a G'=(V',E') si hay una biyección j: V V' tal que x,yΠE si y solo si j(x)j(y)ΠE'. Entonces dos grafos isomorfos tienen el mismo orden y el mismo tamaño.

El tamaño de un grafo de orden n es al menos 0 y a lo sumo ( 2n). Un grafo de orden n y tamaño (2n) se llama un n-grafo completo2 y se denota por Kn; un n-grafo vació En tiene orden n y ningún vértice. En todo Kn todo par de vértices son adyacentes, mientras que en En ningún par de vértices son adyacentes.

El conjunto de vértices adyacentes a un vértice xΠG, se denota por G(x). El grado de x es g(x)= G(x). El grado mínimo de los vértices de un grafo se denota por d(G), mientras que el grado máximo se denota por D(G). Un vértice de grado 0 se dice que es un vértice aislado. Si d(G)=D(G)=k, es decir todo vértice es de grado k entonces se dice que G es k-regular o regular de grado k. Un grafo es regular si es k-regular para algú
k.
Tipos de ordenamiento

ordenamiento es un algoritmo que pone elementos de una lista o un vector en una secuencia dada por una relación de orden, es decir, el resultado de salida ha de ser una permutación —o reordenamiento— de la entrada que satisfaga la relación de orden dada. Las relaciones de orden más usadas son el orden numérico y el orden lexicográfico. Ordenamientos eficientes son importantes para optimizar el uso de otros algoritmos (como los de búsqueda y fusión) que requieren listas ordenadas para una ejecución rápida. También es útil para poner datos en forma canónica y para generar resultados legibles por humanos.
Desde los comienzos de la computación, el problema del ordenamiento ha atraído gran cantidad de investigación, tal vez debido a la complejidad de resolverlo eficientemente a pesar de su planteamiento simple y familiar. Por ejemplo, BubbleSort fue analizado desde 1956.1 Aunque muchos puedan considerarlo un problema resuelto, nuevos y útiles algoritmos de ordenamiento se siguen inventado hasta el día de hoy (por ejemplo, el ordenamiento de biblioteca se publicó por primera vez en el 2004). Los algoritmos de ordenamiento son comunes en las clases introductorias a la computación, donde la abundancia de algoritmos para el problema proporciona una gentil introducción a la variedad de conceptos núcleo de los algoritmos, comonotación de O mayúscula, algoritmos divide y vencerás, estructuras de datos, análisis de los casos peor, mejor, y promedio, y límites inferiores.

tipos de ordenamiento
QuickSort
El ordenamiento rápido (quicksort en inglés) es un algoritmo creado por el científico británico en computación C. A. R. Hoare basado en la técnica de divide y vencerás, que permite, en promedio, ordenar n elementos en un tiempo proporcional a n log n
El algoritmo consta de los siguientes pasos:
  • Elegir un elemento de la lista de elementos a ordenar, al que llamaremos pivote.
  • Resituar los demás elementos de la lista a cada lado del pivote, de manera que a un lado queden todos los menores que él, y al otro los mayores. Los elementos iguales al pivote pueden ser colocados tanto a su derecha como a su izquierda, dependiendo de la implementación deseada. En este momento, el pivote ocupa exactamente el lugar que le corresponderá en la lista ordenada.
  • La lista queda separada en dos sublistas, una formada por los elementos a la izquierda del pivote, y otra por los elementos a su derecha.
  • Repetir este proceso de forma recursiva para cada sublista mientras éstas contengan más de un elemento. Una vez terminado este proceso todos los elementos estarán ordenados.
Como se puede suponer, la eficiencia del algoritmo depende de la posición en la que termine el pivote elegido.
  • En el mejor caso, el pivote termina en el centro de la lista, dividiéndola en dos sublistas de igual tamaño. En este caso, el orden de complejidad del algoritmo es O(n·log n).
  • En el peor caso, el pivote termina en un extremo de la lista. El orden de complejidad del algoritmo es entonces de O(n²). El peor caso dependerá de la implementación del algoritmo, aunque habitualmente ocurre en listas que se encuentran ordenadas, o casi ordenadas. Pero principalmente depende del pivote, si por ejemplo el algoritmo implementado toma como pivote siempre el primer elemento del array, y el array que le pasamos está ordenado, siempre va a generar a su izquierda un array vacío, lo que es ineficiente.
  • En el caso promedio, el orden es O(n·log n).


Ordenamiento Burbuja
La Ordenación de burbuja (Bubble Sort en inglés) es un sencillo algoritmo de ordenamiento. Funciona revisando cada elemento de la lista que va a ser ordenada con el siguiente, intercambiándolos de posición si están en el orden equivocado. Es necesario revisar varias veces toda la lista hasta que no se necesiten más intercambios, lo cual significa que la lista está ordenada. Este algoritmo obtiene su nombre de la forma con la que suben por la lista los elementos durante los intercambios, como si fueran pequeñas "burbujas". También es conocido como el método del intercambio directo. Dado que solo usa comparaciones para operar elementos, se lo considera un algoritmo de comparación, siendo el más sencillo de implementar.

Una manera simple de expresar el ordenamiento de burbuja en pseudocódigo es la siguiente:

   { \color{Sepia} \mathit{ procedimiento }} \;
   { \color{Blue}  \mathit{ DeLaBurbuja }} \; 
   (
      { \color{Black}  \mathit{ a }}
      { \color{Plum}   \mathit{ {}_0 }} ,
      { \color{Black}  \mathit{ a }}
      { \color{Plum}   \mathit{ {}_1 }} ,
      { \color{Black}  \mathit{ a }}
      { \color{Plum}   \mathit{ {}_2 }} ,
      \ldots,
      { \color{Black}  \mathit{ a }} {}_(
      { \color{black}  \mathit{ {}_n }}
      { \color{Blue}   \mathit{ {}_- }}
      { \color{Plum}   \mathit{ {}_1}} {}_)
   )

   { \color{Sepia} \mathit{ para }} \;
   { \color{Black} \mathit{ i}} \;
   { \color{Blue}  \mathit{ \gets }} \;
   { \color{Plum}  \mathit{ 2}} \;
   { \color{Sepia} \mathit{ hasta }} \;
   { \color{Black} \mathit{ n}} \;
   { \color{Sepia} \mathit{ hacer }}

   { \color{Sepia} \mathit{ para }} \;
   { \color{Black} \mathit{ j}} \;
   { \color{Blue}  \mathit{ \gets }} \;
   { \color{Plum} \mathit{ 0}} \;
   { \color{Sepia} \mathit{ hasta }} \;
   { \color{Black} \mathit{ n }} \;
   { \color{Blue}  \mathit{ - }} \;
   { \color{Black} \mathit{ i }} \;
   { \color{Sepia} \mathit{ hacer }}

   { \color{Sepia} \mathit{ si }} \;
   { \color{Black} \mathit{ a }}    {}_(
   { \color{Black} \mathit{ {}_j }} {}_) \;
   { \color{Blue}  \mathit{ > }} \;
   { \color{Black} \mathit{ a }} {}_(
   { \color{Black} \mathit{ {}_j }}
   { \color{Blue}  \mathit{ {}_+ }}
   { \color{Plum}  \mathit{ {}_1}} {}_) \;
   { \color{Sepia} \mathit{ entonces }}

   { \color{Black} \mathit{ aux }} \;
   { \color{Blue}  \mathit{ \gets }} \;
   { \color{Black} \mathit{ a }}    {}_(
   { \color{Black} \mathit{ {}_j }} {}_) \;

   { \color{Black} \mathit{ a }}    {}_(
   { \color{Black} \mathit{ {}_j }} {}_) \;
   { \color{Blue}  \mathit{ \gets }} \;
   { \color{Black} \mathit{ a }} {}_(
   { \color{Black} \mathit{ {}_j }}
   { \color{Blue}  \mathit{ {}_+ }}
   { \color{Plum}  \mathit{ {}_1}} {}_)

   { \color{Black} \mathit{ a }} {}_(
   { \color{Black} \mathit{ {}_j }}
   { \color{Blue}  \mathit{ {}_+ }}
   { \color{Plum}  \mathit{ {}_1}} {}_) \;
   { \color{Blue}  \mathit{ \gets }} \;
   { \color{Black} \mathit{ aux }}

   { \color{Sepia} \mathit{ fin \; si }}

   { \color{Sepia} \mathit{ fin \; para }}

   { \color{Sepia} \mathit{ fin \; para }}

   { \color{Sepia} \mathit{ fin \; procedimiento }}
Este algoritmo realiza el ordenamiento de una lista a den valores, en este caso de n términos numerados del 0al n-1, consta de dos bucles anidados uno con el índicei, que da un tamaño menor al recorrido de la burbuja en sentido inverso de 2 a n, y un segundo bucle con el índice j, con un recorrido desde 0 hasta n-i, para cada iteración del primer bucle, que indica el lugar de la burbuja.
La burbuja son dos términos de la lista seguidos, j yj+1, que se comparan, si el primero es menor que el segundo sus valores se intercambian.
Esta comparación se repite en el centro de los dos bucles, dando lugar a la postre a una lista ordenada, puede verse que el número de repeticiones sola depende de n, y no del orden de los términos, esto es, si pasamos al algoritmo una lista ya ordenada, realizara todas las comparaciones exactamente igual que para una lista no ordenada, esta es una característica de este algoritmo, luego veremos una variante que evita este inconveniente.
Para comprender el funcionamiento, veamos un ejemplo sencillo:
Tenemos una lista de números que hay que ordenar:

   a = \{55, 86, 48, 16, 82 \}  \,

  \begin{array}{r}
      a_{4} = 82 \\
      a_{3} = 16 \\
      a_{2} = 48 \\
      a_{1} = 86 \\
      a_{0} = 55 
   \end{array}
Podemos ver que la lista que tiene cinco términos, luego:

   n = 5 \,
El índice i hará un recorrido de 2 hasta n:

   { \color{Sepia} \mathit{ para }} \;
   { \color{Black} \mathit{ i}} \;
   { \color{BlueViolet} \mathit{ \gets }} \;
   { \color{Black} \mathit{ 2}} \;
   { \color{Sepia} \mathit{ hasta }} \;
   { \color{Black} \mathit{ n}} \;
   { \color{Sepia} \mathit{ hacer }}
Que en este caso será de 2 a 5. Para cada uno de los valores de ij tomara sucesivamente los valores de 0 hasta n-i:

   { \color{Sepia} \mathit{ para }} \;
   { \color{Black} \mathit{ j}} \;
   { \color{BlueViolet} \mathit{ \gets }} \;
   { \color{Black} \mathit{ 0}} \;
   { \color{Sepia} \mathit{ hasta }} \;
   { \color{Black} \mathit{ n-i}} \;
   { \color{Sepia} \mathit{ hacer }}
Para cada valor de j, obtenido en ese orden, se compara el valor del índice j con el siguiente:

   { \color{Sepia}      \mathit{ si }} \;
   { \color{Black} a_{(j)} } \;
   { \color{BlueViolet} > } \;
   { \color{Black} a_{(j+1)}} \;
   { \color{Sepia}      \mathit{ entonces }}
Si el termino j es menor, en su caso podría se mayor, que el termino j+1, los valores se permutan, en caso contrario se continúa con la iteración.

  \begin{array}{r||r|r|r|r|r}
            & j =  0 & j =  1 & j =  2 & j =  3 &    \\
      \hline
      a_{4} &     82 &     82 &     82 & \to 82 & 86 \\
      a_{3} &     16 &     16 & \to 16 & \to 86 & 82 \\
      a_{2} &     48 & \to 48 & \to 86 &     16 & 16 \\
      a_{1} & \to 86 & \to 86 &     48 &     48 & 48 \\
      a_{0} & \to 55 &     55 &     55 &     55 & 55
   \end{array}
Para el caso del ejemplo, tenemos que:

   n = 5 \,
Para la primera iteración del primer bucle:

   i = 2 \,
j tomara los valores de 0 hasta 3:

   { \color{Sepia} \mathit{ para }} \;
   { \color{Black} \mathit{ j}} \;
   { \color{BlueViolet} \mathit{ \gets }} \;
   { \color{Black} \mathit{ 0}} \;
   { \color{Sepia} \mathit{ hasta }} \;
   { \color{Black} \mathit{ 3}} \;
   { \color{Sepia} \mathit{ hacer }}
Cuando j vale 0, se comparan  a_0 \; a_1 , el 55 y el 86, dado que 55 < 86 no se permutan el orden.
Ahora j vale 1 y se comparan  a_1 \; a_2  el 86 y el 48 Como 86 > 48, se permutan, dando lugar a una nueva lista.
Se repite el proceso hasta que j valga 3, dando lugar a una lista parcialmente ordenada, podemos ver que el termino de mayor valor esta en el lugar más alto.

  \begin{array}{r||r|r|r|r}
            & j =  0 & j =  1 & j =  2 &    \\
      \hline
      a_{4} &     86 &     86 &     86 & 86 \\
      a_{3} &     82 &     82 & \to 82 & 82 \\
      a_{2} &     16 & \to 16 & \to 55 & 55 \\
      a_{1} & \to 48 & \to 55 &     16 & 16 \\
      a_{0} & \to 55 &     48 &     48 & 48
   \end{array}
Ahora i vale 3, y j hará un recorrido de 0 a 2.
Primero j vale 0, se comparan  a_0 \; a_1 , el 55 y el 48, como 55 > 48 se permutan dando lugar a la nueva lista.
Para j = 1 se compara el 55 con el 16 y se cambian de orden.
Para j = 2 se compara el 55 y el 82 y se dejan como están, finalizando el bucle con una lista mejor ordenada, puede verse que los dos valores más altos ya ocupan su lugar. No se ha realizado ninguna comparación con el termino cuarto, dado que ya se sabe que después del primer ciclo es el mayor de la lista.
El algoritmo consiste en comparaciones sucesivas de dos términos consecutivos, ascendiendo de abajo a arriba en cada iteración, como la ascensión de las burbujas de aire en el agua, de ahí el nombre del procedimiento, en la primera iteración el recorrido ha sido completo, en el segundo se ha dejado él último termino, al tener ya el mayor de los valores, en los sucesivos sé ira dejando de realizar las ultimas comparaciones, como se puede ver.

  \begin{array}{r||r|r|r}
            & j =  0 & j =  1 &    \\
      \hline
      a_{4} &     86 &     86 & 86 \\
      a_{3} &     82 &     82 & 82 \\
      a_{2} &     55 & \to 55 & 55 \\
      a_{1} & \to 16 & \to 48 & 48 \\
      a_{0} & \to 48 &     16 & 16
   \end{array}
Ahora ya i vale 4 y j recorrerá los valores de 0 a 1.
Cuando j vale 0, se comparan  a_0 \; a_1  esto es el 48 y el 16 dado que 48 es mayor que 16 se permutan los valores, dando lugar a una lista algo más ordenada que la anterior, desde esta nueva ordenación, j pasa a valer 1, con lo que se comparan los términos  a_1 \; a_2  el 48 y el 55 que quedan en el mismo orden.
En este caso la burbuja ha ascendido menos que en los casos anteriores, y la lista esta ya ordenada, pero el algoritmo tendrá que completarse, realizando una ultima iteración.
Hay que tener en cuenta que el bucle para realiza un número fijo de repeticiones y para finalizar tendrán que completarse, aun en el caso extremo, de que la lista estaría previamente ordenada.
Por último i vale 5 y j solo puede vale 0, con lo que solo se realizara una comparación de  a_0 \; a_1 el 16 y el 48, que ya están ordenados y se dejan igual.

  \begin{array}{r||r|r}
            & j =  0 &     \\
      \hline
      a_{4} &     86 & 86 \\
      a_{3} &     82 & 82 \\
      a_{2} &     55 & 55 \\
      a_{1} & \to 48 & 48 \\
      a_{0} & \to 16 & 16
   \end{array}
Los bucles finalizan y también el procedimiento, dejando la lista ordenada.
Una variante que finaliza en caso de que la lista este ordenada, puede ser la siguiente, empleando un centinela ordenado, que detecta que no se ha modificado la lista en un recorrido de la burbuja, y que por tanto la lista ya esta ordenada, finalizando.
Metodo Shell
El ordenamiento Shell (Shell sort en inglés) es un algoritmo de ordenamiento. El método se denomina Shell en honor de su inventor Donald Shell. Su implementación original, requiere O(n2) comparaciones e intercambios en el peor caso. Un cambio menor presentado en el libro de V. Pratt produce una implementación con un rendimiento de O(n log2 n) en el peor caso. Esto es mejor que las O(n2) comparaciones requeridas por algoritmos simples pero peor que el óptimo O(n log n). Aunque es fácil desarrollar un sentido intuitivo de cómo funciona este algoritmo, es muy difícil analizar su tiempo de ejecución.
El Shell sort es una generalización del ordenamiento por inserción, teniendo en cuenta dos observaciones:
  1. El ordenamiento por inserción es eficiente si la entrada está "casi ordenada".
  2. El ordenamiento por inserción es ineficiente, en general, porque mueve los valores sólo una posición cada vez.
El algoritmo Shell sort mejora el ordenamiento por inserción comparando elementos separados por un espacio de varias posiciones. Esto permite que un elemento haga "pasos más grandes" hacia su posición esperada. Los pasos múltiples sobre los datos se hacen con tamaños de espacio cada vez más pequeños. El último paso del Shell sort es un simple ordenamiento por inserción, pero para entonces, ya está garantizado que los datos del vector están casi ordenados.
Considere un valor pequeño que está inicialmente almacenado en el final del vector. Usando un ordenamiento O(n2) como el ordenamiento de burbuja o el ordenamiento por inserción, tomará aproximadamente n comparaciones e intercambios para mover este valor hacia el otro extremo del vector. El Shell sort primero mueve los valores usando tamaños de espacio gigantes, de manera que un valor pequeño se moverá bastantes posiciones hacia su posición final, con sólo unas pocas comparaciones e intercambios.
Uno puede visualizar el algoritmo Shell sort de la siguiente manera: coloque la lista en una tabla y ordene las columnas (usando unordenamiento por inserción). Repita este proceso, cada vez con un número menor de columnas más largas. Al final, la tabla tiene sólo una columna. Mientras que transformar la lista en una tabla hace más fácil visualizarlo, el algoritmo propiamente hace su ordenamiento en contexto (incrementando el índice por el tamaño de paso, esto es usando i += tamaño_de_paso en vez de i++).
Por ejemplo, considere una lista de números como [ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ]. Si comenzamos con un tamaño de paso de 8, podríamos visualizar esto dividiendo la lista de números en una tabla con 5 columnas. Esto quedaría así:
13 14 94 33 82
25 59 94 65 23
45 27 73 25 39
10
Entonces ordenamos cada columna, lo que nos da
10 14 73 25 23
13 27 94 33 39
25 59 94 65 82
45
Cuando lo leemos de nuevo como una única lista de números, obtenemos [ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ]. Aquí, el 10 que estaba en el extremo final, se ha movido hasta el extremo inicial. Esta lista es entonces de nuevo ordenada usando un ordenamiento con un espacio de 3 posiciones, y después un ordenamiento con un espacio de 1 posición (ordenamiento por inserción simple).
El Shell sort lleva este nombre en honor a su inventor, Donald Shell, que lo publicó en 1959. Algunos libros de texto y referencias antiguas le llaman ordenación "Shell-Metzner" por Marlene Metzner Norton, pero según Metzner, "No tengo nada que ver con el algoritmo de ordenamiento, y mi nombre nunca debe adjuntarse a éste.

Metodo de Insercion
El ordenamiento por inserción (insertion sort en inglés) es una manera muy natural de ordenar para un ser humano, y puede usarse fácilmente para ordenar un mazo de cartas numeradas en forma arbitraria. Requiere O(n²) operaciones para ordenar una lista de n elementos.
Inicialmente se tiene un solo elemento, que obviamente es un conjunto ordenado. Después, cuando hay k elementos ordenados de menor a mayor, se toma el elemento k+1 y se compara con todos los elementos ya ordenados, deteniéndose cuando se encuentra un elemento menor (todos los elementos mayores han sido desplazados una posición a la derecha). En este punto se inserta el elemento k+1 debiendo desplazarse los demás elementos.

Ejemplo de funcionamiento

En el siguiente ejemplo, 32 debe ser insertado entre 26 y 47, y por lo tanto 47, 59 y 96 deben ser desplazados.
               k+1
11 26 47 59 96 32 
11 26    47 59 96
11 26 32 47 59 96

En la implementación computacional, el elemento k+1 va comparándose de atrás para adelante, deteniéndose con el primer elemento menor. Simultáneamente se van haciendo los desplazamientos.
11 26 47 59 96 32
11 26 47 59    96
11 26 47    59 96
11 26    47 59 96
11 26 32 47 59 96

El algoritmo en pseudocódigo (con listas que empiezan por 0) debería ser como el siguiente:
algoritmo insertSort( A : lista de elementos ordenables )
    para i=1 hasta longitud(A) hacer
         index=A[i]
         j=i-1
         mientras j>=0 y A[j]>index hacer
              A[j+1] = A[j]
              j = j - 1
         fin mientras
         A[j+1] = index
    fin para
fin algoritmo

Aunque este algoritmo tiene un mejor orden de complejidad que el de burbuja, es muy ineficiente al compararlo con otros algoritmos comoquicksort. Sin embargo, para listas relativamente pequeñas el orden por inserción es una buena elección, no sólo porque puede ser más rápido para cantidades pequeñas de elementos sino particularmente debido a su facilidad de programación.
Metodo secuencial
La búsqueda secuencial es la técnica más simple para buscar un elemento en un arreglo. Consiste en recorrer el arreglo elemento a elemento e ir comparando con el valor buscado (clave). Se empieza con la primera casilla del arreglo y se observa una casilla tras otra hasta que se encuentra el elemento buscado o se han visto todas las casillas. El resultado de la búsqueda es un solo valor, y será la posición del elemento buscado o cero. Dado que el arreglo no está en ningún orden en particular, existe la misma probabilidad de que el valor se encuentra ya sea en el primer elemento, como en el último. Por lo tanto, en promedio, el programa tendrá que comparar el valor buscado con la mitad de los elementos del arreglo.
El método de búsqueda lineal funciona bien con arreglos pequeños o para arreglos no ordenados. Si el arreglo está ordenado, se puede utilizar la técnica de alta velocidad de búsqueda binaria, donde se reduce sucesivamente la operación eliminando repetidas veces la mitad de la lista restante.









sábado, 5 de noviembre de 2011

Arboles
Es una estructura de datos ampliamente usada que imita la forma de un árbol (un conjunto de nodos conectados). Un nodo es la unidad sobre la que se construye el árbol y puede tener cero o más nodos hijos conectados a él. Se dice que un nodo a es padre de un nodo b si existe un enlace desde a hasta b (en ese caso, también decimos que b es hijo de a). Sólo puede haber un único nodo sin padres, que llamaremos raíz. Un nodo que no tiene hijos se conoce como hoja. Los demás nodos (tienen padre y uno o varios hijos) se les conoce como rama.




Formalmente, podemos definir un árbol de la siguiente forma:
  • Caso base: un árbol con sólo un nodo (es a la vez raíz del árbol y hoja).
  • Un nuevo árbol a partir de un nodo nr y k árboles  de raíces  con  elementos cada uno, puede construirse estableciendo una relación padre-hijo entre nr y cada una de las raíces de los k árboles. El árbol resultante de  nodos tiene como raíz el nodo nr, los nodos  son los hijos de nr y el conjunto de nodos hoja está formado por la unión de los k conjuntos hojas iniciales. A cada uno de los árboles Ai se les denota ahora subárboles de la raíz.
Una sucesión de nodos del árbol, de forma que entre cada dos nodos consecutivos de la sucesión haya una relación de parentesco, decimos que es un recorrido árbol. Existen dos recorridos típicos para listar los nodos de un árbol: primero en profundidad y primero en anchura. En el primer caso, se listan los nodos expandiendo el hijo actual de cada nodo hasta llegar a una hoja, donde se vuelve al nodo anterior probando por el siguiente hijo y así sucesivamente. En el segundo, por su parte, antes de listar los nodos de nivel n + 1 (a distancia n+ 1 aristas de la raíz), se deben haber listado todos los de nivel n. Otros recorridos típicos del árbol son preordenpostorden e inorden:
  • El recorrido en preorden, también llamado orden previo consiste en recorrer en primer lugar la raíz y luego cada uno de los hijos  en orden previo.
  • El recorrido en inorden, también llamado orden simétrico (aunque este nombre sólo cobra significado en los árboles binarios) consiste en recorrer en primer lugar A1, luego la raíz y luego cada uno de los hijos  en orden simétrico.
  • El recorrido en postorden, también llamado orden posterior consiste en recorrer en primer lugar cada uno de los hijos  en orden posterior y por último la raíz.
Finalmente, puede decirse que esta estructura es una representación del concepto de árbol en teoría de grafos. Un árbol es un grafo conexoacíclico (ver también teoría de grafos y Glosario en teoría de grafos).

Arboles Binarios
-Enlazar los hijos de cada nodo en forma horizontal(los hermanos=.
-Relacionar en forma vertical el nodo padre con el lujo que se encuentre con el hijo que se encuentra mas a la izquierda. Ademas, se debe eliminar el vinculo de ese padre con el resto de los hijos.
-Respetar el diagrama resultante aproximadamente 45grados a la izquierda y así se obtendrá un árbol binario correspondiente

Bosque
Representa un conjunto normalmente ordenado de uno o mas arboles generales
Archivo:Tree graph.svg
Conversión al árbol binario
-Enlazar en forma horizontal las raíces de los distraídos árboles generales.
-Relacionar los lujos de cada nodo(los hermanos) en forma horizontal.
-Enlazar en forma vertical el nodo padre con el hijo que se encuentra más a la izquierda. Además se debe eliminar el vinculo del padre con el resto de los hijos.
-Restar el diagrama resultante aproximadamente 45 grados hacia la izquierda y así obtendrá el árbol binario correspondiente.
package treeframe;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
import java.util.*;

/**
 *
 * @author pc132-43
 */
public class NewClass
{
      public static void main(String[] args)
   {  JFrame NewClass = new SimpleTreeFrame();
      NewClass.show();
   }
}
class SimpleTreeFrame extends JFrame
{
   DefaultMutableTreeNode root = new DefaultMutableTreeNode("Mundo");
   DefaultMutableTreeNode arge = new DefaultMutableTreeNode("Argentina");
   DefaultMutableTreeNode sant = new DefaultMutableTreeNode("Santa Fe");
   DefaultMutableTreeNode rafa = new DefaultMutableTreeNode("Rafaela");
   DefaultMutableTreeNode rosa = new DefaultMutableTreeNode("Rosario");
   DefaultMutableTreeNode safe = new DefaultMutableTreeNode("Santa Fe");
   DefaultMutableTreeNode vena = new DefaultMutableTreeNode("Venado Tuerto");
   DefaultMutableTreeNode vill = new DefaultMutableTreeNode("Villa Constitucion");
   DefaultMutableTreeNode cord = new DefaultMutableTreeNode("Cordoba");
   DefaultMutableTreeNode codo = new DefaultMutableTreeNode("Cordoba");
   DefaultMutableTreeNode cbro = new DefaultMutableTreeNode("Cura Brochero");
   DefaultMutableTreeNode rcua = new DefaultMutableTreeNode("Rio Cuarto");
   DefaultMutableTreeNode chac = new DefaultMutableTreeNode("Chaco");
   DefaultMutableTreeNode resi = new DefaultMutableTreeNode("Resistencia");
   DefaultMutableTreeNode vang = new DefaultMutableTreeNode("Villa Angela");
   DefaultMutableTreeNode chil = new DefaultMutableTreeNode("Chile");
   DefaultMutableTreeNode regi = new DefaultMutableTreeNode("Region Metropolitana");
   DefaultMutableTreeNode schi = new DefaultMutableTreeNode("Santiago de Chile");
   public SimpleTreeFrame()
   {  setTitle("SimpleTree");
      setSize(300, 200);
      addWindowListener(new WindowAdapter()
         {  public void windowClosing(WindowEvent e)
            {  System.exit(0);
            }
         } );
      root.add(arge);                                                   // Enlazado de nodos
      arge.add(sant);                                                   // Enlazado de nodos
      sant.add(rafa);                                                   // Enlazado de nodos
      sant.add(rosa);                                                   // Enlazado de nodos
      sant.add(safe);                                                   // Enlazado de nodos
      sant.add(vena);                                                   // Enlazado de nodos
      sant.add(vill);                                                   // Enlazado de nodos
      arge.add(cord);                                                   // Enlazado de nodos
      cord.add(codo);                                                   // Enlazado de nodos
      cord.add(cbro);                                                   // Enlazado de nodos
      cord.add(rcua);                                                   // Enlazado de nodos
      arge.add(chac);                                                   // Enlazado de nodos
      chac.add(resi);                                                   // Enlazado de nodos
      chac.add(vang);                                                   // Enlazado de nodos
      root.add(chil);                                                   // Enlazado de nodos
      chil.add(regi);                                                   // Enlazado de nodos
      regi.add(schi);                                                   // Enlazado de nodos
      JTree tree = new JTree(root);
      Container contentPane = getContentPane();
      contentPane.add(new JScrollPane(tree));
      Enumeration hijos = sant.children();                              // Enumeracion de hijos
      while ( hijos.hasMoreElements() )                                 // Enumeracion de hijos
      {                                                                 // Enumeracion de hijos
        System.err.println("Hijos de Santa Fe : "+hijos.nextElement()); // Enumeracion de hijos
      }                                                                 // Enumeracion de hijos
      boolean hoja = vena.isLeaf();                                     // Consulta Hoja
      System.err.println("Es Venado Tuerto hoja : "+hoja);              // Consulta Hoja
      Enumeration breadth = root.breadthFirstEnumeration();             // Enumeracion Nodos
      while ( breadth.hasMoreElements() )                               // Enumeracion Nodos
      {                                                                 // Enumeracion Nodos
        System.err.println("Breadth First : "+breadth.nextElement());   // Enumeracion Nodos
      }                                                                 // Enumeracion Nodos
      Enumeration depth = root.depthFirstEnumeration();                 // Enumeracion Nodos
      while ( depth.hasMoreElements() )                                 // Enumeracion Nodos
      {                                                                 // Enumeracion Nodos
        System.err.println("Depth First : "+depth.nextElement());       // Enumeracion Nodos
      }                                                                 // Enumeracion Nodos
      Enumeration preorder = root.preorderEnumeration();                // Enumeracion Nodos
      while ( preorder.hasMoreElements() )                              // Enumeracion Nodos
      {                                                                 // Enumeracion Nodos
        System.err.println("Pre Order : "+preorder.nextElement());      // Enumeracion Nodos
      }                                                                 // Enumeracion Nodos
      Enumeration postorder = root.postorderEnumeration();              // Enumeracion Nodos
      while ( postorder.hasMoreElements() )                             // Enumeracion Nodos
      {                                                                 // Enumeracion Nodos
        System.err.println("Post Order : "+postorder.nextElement());    // Enumeracion Nodos
      }                                                                 // Enumeracion Nodos
   }
}