Ordenamiento

ORDENAMIENTO 
Concepto de Ordenamiento
 Uno de los procedimientos más comunes y útiles en el procesamiento de datos, es la clasificación u ordenación de los mismos. Se considera ordenar al proceso de reorganizar un conjunto dado de objetos en una secuencia determinada. Cuando se analiza un método de ordenación, hay que determinar cuántas comparaciones e intercambios se realizan para el caso más favorable, para el caso medio y para el caso más desfavorable.
 La colocación en orden de una lista de valores se llama Ordenación. Por ejemplo, se podría disponer una lista de valores numéricos en orden ascendente o descendente, o bien una lista de nombres en orden alfabético. La localización de un elemento de una lista se llama búsqueda.
Tipos de métodos de ordenamiento
Algoritmos de ordenamiento
 Debido a que las estructuras de datos son utilizadas para almacenar información, para poder recuperar esa información de manera eficiente es deseable que aquella esté ordenada. Existen varios métodos para ordenar las diferentes estructuras de datos básicas.
En general los métodos de ordenamiento no son utilizados con frecuencia, en algunos casos sólo una vez. Hay métodos muy simples de implementar que son útiles en los casos en dónde el número de elementos a ordenar no es muy grande (ej, menos de 500 elementos). Por otro lado hay métodos sofisticados, más difíciles de implementar pero que son más eficientes en cuestión de tiempo de ejecución.
Los métodos sencillos por lo general requieren de aproximadamente n x n pasos para ordenar n elementos.
Los métodos simples son: insertion sort (o por inserción directa) selection sort, bubble sort, y shellsort, en dónde el último es una extensón al insertion sort, siendo más rápido. 
  • Insertion Sort (Inserción)
  • Shell Sort (Shell)
  • Bubble Sort (Burbuja)
  • Partition-Exchange Sort o QuickSort (Ordenación Rápida)
QuickSort.
 Si bien el método de la burbuja era considerado como el peor método de ordenación simple o menos eficiente, el método Quicksort basa su estrategia en la idea intuitiva de que es más fácil ordenar una gran estructura de datos subdividiéndolas en otras más pequeñas introduciendo un orden relativo entre ellas. En otras palabras, si dividimos el array a ordenar en dos subarrays de forma que los elementos del subarray inferior sean más pequeños que los del subarray superior, y aplicamos el método reiteradamente, al final tendremos el array inicial totalmente ordenado. Existen además otros métodos conocidos, el de ordenación por montículo y el de shell.

Inserción.
 El fundamento de este método consiste en insertar los elementos no ordenados del arreglo en subarreglos del mismo que ya estén ordenados. Dependiendo del método elegido para encontrar la posición de inserción tendremos distintas versiones del método de inserción.

ShellSort
 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.

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.

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:33 37 4:48 5:57 6: 7: 8:86 9:92Lista ordenada:
12 25 33 37 48 57 86 92


Codigo:
Burbuja
package ordenaburbuja;
public class OrdenaAlgoritmo
 {
//Esto no se necesita ya que por lógica ya que es usado con el método de ordenamiento mejorado
public static void ordenar( int [] arreglo)
{
int pasadas = 0;
int comparaciones = 0;
for (int i = 0; i < arreglo.length; i++) //Aquí se están declarando las variables a usar en el ciclo con el cual daremos las revisiones para el ordenamiento
{
     ++pasadas;
     for (int j = 0; j < arreglo.length - 1; j++)
{
  ++comparaciones;
  if (arreglo[j] > arreglo[j + 1]) //Se está checando que si el número del arreglo es mayor haremos intercambio de posiciones
{
      intercambiar(arreglo, j, j+1);
  }
     }
 }
 estadisticas(pasadas, comparaciones);
    }
    public static void ordenarMejorado( int [] arreglo)
{
 int pasadas = 0;
 int comparaciones = 0;
 boolean hayCambios = true;
 for (int i = 0; hayCambios ; i++)
 {
//No necesariamente tenemos que usar el booleano
     ++pasadas;
     hayCambios = false;
     for (int j = 0; j < arreglo.length - 1; j++)
{
  ++comparaciones;
  if (arreglo[j] > arreglo[j + 1]) // De nuevo hacemos cambio de posiciones
{
      intercambiar(arreglo, j, j+1);
      hayCambios = true;
  }
     }
 }
 estadisticas(pasadas, comparaciones);// Esta parte no se utiliza.
    }
    private static void intercambiar(int [] arreglo, int a, int b)
 {
//Esta parte no se utiliza
 int tmp = arreglo[a];
 arreglo[a] = arreglo[b];
 arreglo[b] = tmp;
    }
    private static void estadisticas( int pasadas, int comparaciones) // Aquí mostraremos en pantalla cuando ya se haiga terminado de ordenar
{
 System.out.println( "Pasadas: " + pasadas );
 System.out.println( "Comparaciones: " + comparaciones );
    }
}
package ordenaburbuja;
public class OrdenaBurbuja
{
public static void  main (String args[])
{
 int [] valores = {15,35,01,05,04,03,19,45,13,02,55,8,
    78,997,451,546,12,16,24,103,99,784,4541,15};
 //OrdenaAlgoritmo.ordenar(valores);
 OrdenaAlgoritmo.ordenarMejorado(valores);
 // Mostrar arreglo.
 
for (int i = 0; i < valores.length ; i++)
     System.out.println ( "valores["+i+"]: "+  valores[i]);
    }
}
QuickSort
Package quicksort;
Public class Ordenador
 {
    public int[] quicksort(int numeros[])//…………………………captando valores enteros para quicksort
    {
        return quicksort(numeros,0,numeros.length-1); //…………….regresa el valor quicksort al arreglo
    }
    public int[] quicksort(int numeros[],int izq,int der) //…………declara números enteros de izquierda a derecha
    {
        if(izq>=der)
//……………………..if si la condición de izquierda es igual a la derecha
            return numeros; //………………….retorna los valores numéricos
        int i=izq,d=der; //…………………… si el entero es igual a izquierda, derecha
        if(izq!=der) //……………………..si la condición de izquierda es igual a derecha
        {
        int pivote; //………………….el entero pivote
        int aux; //………………..int es auxiliar
        pivote = izq; //……………..el pivote va a la izquierda
        while(izq!=der) //……………………..mientras que la izquierda es igual a la derecha
        {imprimeArreglo(numeros); //………………………imprime los arreglos de numeros
         while(numeros[der]>=numeros[pivote] && izq<der) //……………mientras que los números son mayor igual de la derecha el pivote hará la acción de ordenarlos de izquierda a derecha
               der--;
           while(numeros[izq]<numeros[pivote] && izq<der) //………..mientras que los números de la izquierda son menor del pivote, se moverán de izquierda a derecha
               izq++;//………….incrementando los de la izquierda
         if(der!=izq) //……………..si la condición de la derecha sea diferente a la izquierda
         {
             aux = numeros[der]; //………………….auxiliar los números  de la derecha en arreglo
            numeros[der]= numeros[izq]; //…………….numeros de la derecha sean iguales a los de la izquierda
            numeros[izq]=aux;} //………………………….. auxiliar los números  de la izquierda en arreglo
        }
        if(izq==der){ //……………..si la condición de la izquierda es igual al de la derecha
            quicksort(numeros,i,izq-1); //………ordenamiento quicksort de números de la izquierda
            quicksort(numeros,izq+1,d); //………….. ordenamiento quicksort de números de la derecha
        }
        }
        else//………………….sino, retorna los números de ambos lados
            return numeros;
       return numeros;
    }

    public void imprimeArreglo(int arreglo[])//……………..imprime el arreglo
    {
        String imp="";
        for(int i=0;i<arreglo.length;i++)//………………ciclo del arreglo de quicksort
        {
            if(i!=arreglo.length-1) //………………….condición si el arreglo puede ejecutar el ciclo
            imp=imp+arreglo[i]+",";
            else
                imp=imp+arreglo[i]+"";
        }
        System.out.println(imp); //…………….imprimir resultados
    }
    public static void main(String[] args) {
        int array[] ={4,2,5,7,6,1,3};//……………………..numeros a ordenar en modo quicksort
Ordenador a = new Ordenador();
a.quicksort(array);
    }
}
Videos:
QuickSort
******************************************************

******************************************************

ShellSort
******************************************************

******************************************************

Burbuja
******************************************************

******************************************************

BÚSQUEDA
La búsqueda es una operación que tiene por objeto la localización de un elemento dentro de la estructura de datos. A menudo un programador estará trabajando con grandes cantidades de datos almacenados en arreglos y pudiera resultar necesario determinar si un arreglo contiene un valor que coincide con algún valor clave o buscado.
Siendo el array de una dimensión o lista una estructura de acceso directo y a su vez de acceso secuencial, encontramos dos técnicas que utilizan estos dos métodos de acceso, para encontrar elementos dentro de un array: búsqueda lineal y búsqueda binaria.

Búsqueda 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.
Búsqueda Binaria:
Se utiliza cuando el vector en el que queremos determinar la existencia de un elemento está previamente ordenado. Este algoritmo reduce el tiempo de búsqueda considerablemente, ya que disminuye exponencialmente el número de iteraciones necesarias.
Está altamente recomendado para buscar en arrays de gran tamaño. Por ejemplo, en uno conteniendo 50.000.000 elementos, realiza como máximo 26 comparaciones (en el peor de los casos).
Para implementar este algoritmo se compara el elemento a buscar con un elemento cualquiera del array (normalmente el elemento central): si el valor de éste es mayor que el del elemento buscado se repite el procedimiento en la parte del array que va desde el inicio de éste hasta el elemento tomado, en caso contrario se toma la parte del array que va desde el elemento tomado hasta el final. De esta manera obtenemos intervalos cada vez más pequeños, hasta que se obtenga un intervalo indivisible. Si el elemento no se encuentra dentro de este último entonces se deduce que el elemento buscado no se encuentra en todo el array.
Búsqueda Hash:
  En informática, hash se refiere a una función o método para generar claves o llaves que representen de manera casi unívoca a un documento, registro, archivo, etc., resumir o identificar un dato a través de la probabilidad, utilizando una función hash o algoritmo hash. Un hash es el resultado de dicha función o algoritmo.

  Una función de hash es una función para resumir o identificar probabilísticamente un gran conjunto de información, dando como resultado un conjunto imagen finito generalmente menor (un subconjunto de los números naturales por ejemplo). Varían en los conjuntos de partida y de llegada y en cómo afectan a la salida similitudes o patrones de la entrada. Una propiedad fundamental del hashing es que si dos resultados de una misma función son diferentes, entonces las dos entradas que generaron dichos resultados también lo son.

  Es posible que existan claves resultantes iguales para objetos diferentes, ya que el rango de posibles claves es mucho menor que el de posibles objetos a resumir (las claves suelen tener en torno al centenar de bits, pero los ficheros no tienen un tamaño límite).

  Son usadas en múltiples aplicaciones, como los arrays asociativos, criptografía, procesamiento de datos y firmas digitales, entre otros. Una buena función de hash es una que experimenta pocas colisiones en el conjunto esperado de entrada; es decir que se podrán identificar unívocamente las entradas (ver función inyectiva).

  Muchos sistemas relacionados con la seguridad informática usan funciones o tablas hash.


Operaciones:

Código:


Videos:
Secuencial

******************************************************

******************************************************
Binaria
******************************************************

******************************************************

Hash
******************************************************

******************************************************

Canal de YouTube, aqui vienen muchos videos de estructura de datos, es de una Universidad de Valencia.
http://www.youtube.com/user/valenciaupv

Bibliografia
http://www.mailxmail.com/curso-aprende-programar/metodos-ordenamiento-busqueda
http://ict.udlap.mx/people/ingrid/Clases/IS211/EDindex.html
http://html.rincondelvago.com/estructura-de-datos_7.html
http://es.wikipedia.org/wiki/Algoritmo_de_b%C3%BAsqueda