Cómo calcular la complejidad del algoritmo de ordenamiento por selección

Aquí una implementación (clásica) en Javascript (puede ejecutarse en un navegador o sugiero en Node.js)

puede ver que hay 3 funciones: swap, indexOfMininum y selectionSort;
Veamos la complejidad:
cada iteración SelectionSort (..) llame a IndexOfMinimum (..) y Swap;
La función de intercambio se ejecuta en tiempo constante sin importar cuán grande sea la matriz, y se llama n veces desde el ciclo dentro de SelectionSort (..) por lo que su complejidad es O (n), de hecho, todo lo que está dentro del ciclo de SelectionSort ( ..) se ejecuta en tiempo constante cada iteración por lo que su complejidad es O (n);
Las cosas comienzan a ponerse interesantes en indexOfMinimum (…) esta función se llama n veces y cada vez que ejecuta un bucle de código de tiempo constante, cada vez que se ejecuta el bucle de indexOfMinimum disminuye su contador total para la próxima iteración … así:

la primera vez se ejecuta n-1 veces, luego n-2, luego n-3, etc.
aquí llegaron las matemáticas, esta es una serie que en forma cerrada (estoy traduciendo estos términos del italiano … no sé si en inglés están bien) salió así:

[matemáticas] n ^ 2/2 + n / 2 (dejo de escribir el cálculo, lo siento pero el editor gana … ese es el resultado) [/ matemáticas]

ignoramos el factor 1/2 y tomamos en cuenta solo el term de orden máximo n ^ 2,
entonces la complejidad de indexOfMinimum es O (n ^ 2).
Entonces tenemos O (n) para cada cosa dentro de SelectionSort (sin IndexOfMinimum) y Swap, y O (n ^ 2) para IndexOfMinimum, podemos decir que el algoritmo SelectionSort tiene una complejidad asintótica de O (n ^ 2).
Otra consideración:
complejidad del mejor caso y el peor de los casos, podemos ver que este algoritmo no tiene ni el mejor caso ni el peor de los casos, IndexOfMinimum siempre ciclará n ^ 2 / n / 2 veces.
¿Cómo se escala? Si aumentamos la entrada en un factor de 1000, el tiempo de ejecución aumentará en un factor de 1 millón.
Espero que esta respuesta sea lo suficientemente clara.

var swap = function (array, firstIndex, secondIndex) {

var temp = array[firstIndex];

array[firstIndex] = array[secondIndex];

array[secondIndex] = temp;

};

var indexOfMinimum = function(array, startIndex) {

var minValue = array[startIndex];

var minIndex = startIndex;

for(var i = minIndex + 1; i < array.length; i++) {

if(array[i] < minValue) {

minIndex = i;

minValue = array[i];

}

}

return minIndex;

};

var selectionSort = function(array) {

var currentIndex=1;

for( var i = 0; i<array.length ; i++){

currentIndex = indexOfMinimum(array,i,currentIndex);

swap(array,i,currentIndex);

}

};

var array = [22, 11, 99, 88, 9, 7, 42];

console.log("Starting Array: "+array);

selectionSort(array);

console.log("Array after sorting: " + array);

var desiredValue = [7, 9, 11, 22, 42, 88, 99]

console.log("must be equal to: " + desiredValue);

Como referencia, aquí está la implementación del algoritmo Selection Sort de Wikipedia, modificada ligeramente para mayor claridad:

int i, j;

int [] arrayToSort = …;
para (j = 0; j int iMin = j;
para (i = j + 1; i if (a [i] iMin = i;
}
}

if (iMin! = j) {
swap (a [j], a [iMin]);
}
}

Para poner en palabras, primero itera sobre cada elemento de la matriz . Esta es su primera pista: será al menos [matemática] O (n) [/ matemática] o lineal sobre el número de elementos. Luego, para cada elemento sobre la matriz, itera sobre cada elemento restante de la matriz . Entonces, para cada elemento, está iterando sobre cada elemento posterior. Debido a que hay n elementos, y está realizando aproximadamente n operaciones en cada elemento, eso es [matemática] О (n²) [/ matemática]. Lo difícil de razonar aquí es el aspecto “más o menos” de esa declaración. Lo clave a tener en cuenta es que, aunque cada iteración interna no está iterando sobre toda la matriz (de tamaño n), está iterando sobre una cantidad que es linealmente proporcional al tamaño de la matriz. Es la misma razón por la que [matemáticas] O (n / 2) [/ matemáticas] o [matemáticas] O (kn) [/ matemáticas] no son válidas; Los coeficientes no importan.

Si aún no está claro, intentemos un enfoque visual. Lo que sigue es una cuadrícula donde el eje y representa cada iteración a través de una matriz de longitud 5 y el eje x representa qué índices de la matriz se leyeron durante esa iteración, y una celda se llena si se leyó el índice de matriz correspondiente durante esa iteración. La cuadrícula está poblada por un algoritmo hipotético diferente , uno donde cada elemento de la matriz, cada otro elemento se lee durante esa iteración:

La longitud y la altura de la cuadrícula es n (longitud de la matriz), y en cada una de las n iteraciones, todos los n elementos se leen, por lo tanto, está completamente lleno (y no hay mucho que ver). Pero está bastante claro que el número total de celdas llenas es n² aquí.

Veamos nuevamente con el algoritmo de selección de selección:

La primera iteración (primera fila) lee todos los elementos. La segunda iteración (segunda fila) lee todos los elementos excepto el primero, etc., y así sucesivamente. Entonces, el número de operaciones (lecturas) como se muestra en el gráfico anterior se parece a un triángulo; aproximadamente la mitad que en la cuadrícula anterior. Teóricamente, la complejidad debería ser O (½n²), ¿verdad? No exactamente; recuerda que los multiplicadores constantes no importan. La ½ cae, y nos quedamos con O (n²).

(¿Por qué no importan los multiplicadores constantes? Esencialmente, O se usa para determinar qué tan bien un algoritmo escala a entradas más grandes. Cuando su entrada aumenta de tamaño en un factor de 100, el algoritmo tarda 100 veces más en ejecutarse (O (n )) ¿O 1,000,000 veces más de tiempo de ejecución (O (n³))? Esto importa más un factor de dos o tres aquí y allá.)

More Interesting

¿Cuál es la complejidad temporal de las funciones incorporadas en C ++?

¿Codeforces tiene un problema de ética?

¿Es necesario codificar todos los datos en estructuras como pilas en C ++, o es un conocimiento práctico suficiente para aclarar entrevistas?

¿Cuál es la complejidad de este algoritmo de conteo de bits?

¿Cuál es la mejor manera de aprender estructuras de datos y Java?

¿Es posible cuantificar la experiencia laboral?

¿Hay un problema DP estándar similar a SPOJ Farida?

¿Cuál es la solución a este décimo problema polinómico de clase?

Creamos un algoritmo de software único para medir / cuantificar las diferencias de las imágenes a escala nano-planetaria. ¿Cómo monetizamos esto?

¿Puede alguien ayudarme a preparar un plan para preparar estructuras de datos y algoritmos en un mes de tiempo desde el punto de vista de las entrevistas?

¿Cuáles son los principales usos de un diagrama de flujo?

¿Para qué tipo de gráfico sería óptimo y correcto un algoritmo codicioso para colorear gráficos?

Soy completamente nuevo en algoritmos. ¿Cuál es el mejor libro / curso / método para realmente entrar en ellos?

¿Debería darse más reconocimiento a las personas que hacen el trabajo de limpiar conjuntos de datos para que puedan ser utilizadas por personas que ejecutan algoritmos de aprendizaje automático?

¿Quién sabe qué hay detrás de la API de Google Nearby Search? ¿Qué algoritmo usan? ¿Cómo encuentra Google una estación de servicio cercana?