0% encontró este documento útil (0 votos)
21 vistas22 páginas

Complejidad Algorítmica y Análisis Eficiente

1) El documento habla sobre la complejidad algorítmica y describe diferentes tipos de complejidad como la complejidad temporal y espacial. 2) Explica cómo calcular la complejidad de algoritmos usando diferentes estructuras de control como secuenciales, alternativas y repetitivas. 3) Introduce la notación asintótica O grande para analizar la complejidad algorítmica y comparar algoritmos independientemente de constantes.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
21 vistas22 páginas

Complejidad Algorítmica y Análisis Eficiente

1) El documento habla sobre la complejidad algorítmica y describe diferentes tipos de complejidad como la complejidad temporal y espacial. 2) Explica cómo calcular la complejidad de algoritmos usando diferentes estructuras de control como secuenciales, alternativas y repetitivas. 3) Introduce la notación asintótica O grande para analizar la complejidad algorítmica y comparar algoritmos independientemente de constantes.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd

Proyecto de Aula – Practica 0

Carlos A. Hernández

Institución Universitaria Politécnico Grancolombiano

M2160-10554 IPA49019 Pensamiento Algorítmico

Instructor Gloria P. Perez

19 septiembre de 2021
2

Tabla de Contenido

Tabla de Contenido 2

Introducción 3

Objetivos 5

Complejidad de los Algoritmos 5

Complejidad temporal y complejidad espacial 6

Complejidad temporal: 6

Complejidad espacial: 7

Reaprovechamiento de cálculos 7

Complejidad Algorítmica de las Estructuras de Control Básicas 7

Complejidad de la combinación de algoritmos 9

Notación asintótica de la complejidad algorítmica 13

Tipos de notación asintótica 14

Comparación de complejidades 15

Propiedades de la notación O 17

Complejidad algorítmica de los tipos abstractos de datos 18

Complejidad del TAD de los números naturales 19

Complejidad del TAD Conjunto 20

Descripción de los Algoritmos con su Referencia 21

Clasificación 21

Estabilidad 23

Sort Burbuja – Pseudocódigo 25


3

Quicksort – Pseudocódigo 26

Eficiencia del Algoritmo 27

Bucket Sort – Pseudocódigo 27

Análisis Comparativo 27

Conclusiones 27

Bibliografía 27

s conocidas T1, T2, ..., Tn, entonces se puede aplicar un conjunto de reglas para calcular

la complejidad del algoritmo A.

• Si dos o más algoritmos se ejecutan secuencialmente

A1

A2

...

An

La complejidad total será la suma de las complejidades parciales, es decir,

T(N) = T1(N) + T2(N) + ... + Tn(N)


4

• Si en una estructura alternativa como la siguiente:

Sí (condición) entonces // condición se denota por C

A1

Sino

A2

Fsi

Entre dos subalgoritmos se ejecuta uno u otro, según se cumpla o no una expresión

(una condición); la complejidad del algoritmo dependerá de qué rama se ejecute. La rama

que se ejecute dependerá de los datos de entrada, pero no de su tamaño. Para diferentes

datos se ejecutará una rama u otra. Por lo tanto, en general no podremos calcular el coste

temporal exacto del algoritmo para datos de tamaño N. Por lo tanto, lo más apropiado

como medida de complejidad sería proporcionar una medida del coste medio para una

ejecución del algoritmo con datos de tamaño N, en función de las veces que se ejecuta

cada rama del algoritmo en término medio. Así pues, la complejidad total será la suma

ponderada de los valores posibles de la función de evaluación para la distribución de

probabilidades {p, 1 – p} más el coste de evaluar la condición TC(N), es decir:

T(N) = p · T1(N) + (1 – p) · T2(N) + TC(N).

Si no se conocen las probabilidades de cada valor resultado de evaluar la expresión,

no podremos calcular el coste medio de una ejecución del algoritmo para datos de tamaño

N. En este caso, una buena medida es considerar que la complejidad total es el máximo

de las complejidades parciales, es decir:


5

T(N) = máx(T1(N),T2(N)) + TC(N).

Eso corresponde a lo que se conoce como análisis del peor caso, que se desarrollará

más adelante, mientras que el caso anterior se corresponde a lo que se conoce como caso

medio. Del mismo modo, si la estructura alternativa sólo tiene una rama, se puede

considerar que, en el peor de los casos (cuando la condición es cierta), la complejidad

total es:

T(N) = T1(N) + TC(N)

• Si en una estructura repetitiva como la siguiente:

Mientras (condición) { // condición se denota por C

Un algoritmo A con complejidad TA(N) se ejecuta dentro de un bucle que depende

exactamente del tamaño del problema N, la complejidad resultante se calcula como:

T(N) = N · TA(N) + (N + 1) · TC(N).

Eso es cierto sólo si el algoritmo A mantiene una complejidad constante a lo largo de

todas las interacciones del bucle. Si no fuera así, y la complejidad dependiera de la interacción,
6

sería necesario hacer una descomposición de las diferentes ejecuciones del algoritmo A y hacer

un sumatorio de la complejidad en cada ejecución, es decir:

Cuando TA(N,j) = TA(N) para toda iteración j (es decir, la complejidad se mantiene

constante), el sumatorio se reduce a N · TA(N).

Del mismo modo, si el bucle ejecuta un número log(N) de veces, la complejidad total se

calcularía como:

Es decir, un bucle que depende del tamaño del problema en función de G(N), incrementa

la complejidad del problema original en G(N) veces, más el coste de evaluar la condición G(N) +

1 veces. Esta regla se aplica directamente en caso de dos o más bucles imbricados de la siguiente

forma:

Mientras (condición1) {// este bucle se ejecuta G1(N) veces

Mientras (condición2) {// y este G2(N) veces

y da una complejidad total (en este caso) de:


7

Es decir, la complejidad crece de manera multiplicativa por cada nivel de bucle.

• Si en una sentencia s (una instrucción o bien la evaluación de una expresión) se hace

una llamada a una función o procedimiento que tiene complejidad Ts (N), se

considera que la sentencia es un subalgoritmo con complejidad Ts (N) y se aplica la

regla de descomposición de un algoritmo en subalgoritmos.

Notación asintótica de la complejidad algorítmica

El uso del número de operaciones básicas ejecutadas por un algoritmo, denotado por

T(N), puede ser complicado para hacer comparaciones entre algoritmos. Para valores pequeños

de N, las constantes que acompañan los términos de T(N) pueden influir muy significativamente

en el coste total que se está evaluando, y pueden llevar a conclusiones erróneas respecto a la

eficiencia del algoritmo. En cambio, lo que interesa es conocer el comportamiento del algoritmo

para valores de N grandes, una situación en la que la elección correcta de un algoritmo puede

permitir reducir la complejidad algorítmica necesaria para resolver un problema de manera

significativa. Un ejemplo claro son los algoritmos de ordenación, en los que, para valores

pequeños de N, los algoritmos simples –como el de inserción, el de selección o el de la burbuja–

pueden ser más eficientes que otros más complejos –por ejemplo, el Quicksort, el shellsort o el

heapsort. En cambio, para valores grandes de N, es bien sabido que estos últimos algoritmos son

mucho más eficientes a pesar de su complejidad intrínseca.


8

Por lo tanto, es necesario disponer de una notación que permita comparar algoritmos

directamente, sin haber de preocuparse por los casos particulares que aparecen cuando se tienen

en cuenta las constantes de las diferentes funciones T(N). Por eso, se usa lo que se conoce como

notación asintótica, que permite hacerse una idea de la complejidad de un algoritmo cuando el

tamaño de la entrada de un problema se hace muy grande.

Tipos de notación asintótica

Dependiendo del tipo de análisis que se realice, podemos encontrar hasta cinco

notaciones asintóticas diferentes. Todas ellas están relacionadas, y algunas son más útiles que

otras según el uso que se les quiera dar. La notación más usada es la llamada O grande, y se

denota por O.

Es decir, informalmente, un algoritmo F tiene complejidad O(G) si el número de

operaciones necesarias queda fijado por el comportamiento de G para valores grandes de N.

Normalmente, las funciones G (órdenes de complejidad) son sencillas, sin constantes. En

realidad, O(G) corresponde a un conjunto de funciones, y con la notación O se consigue poner en

un mismo conjunto todas las funciones con costes “comparables”, es decir, equivalentes con

independencia de factores externos (hardware, sistema operativo, lenguaje de programación,

etc.). Respecto a la constante C, su presencia en la definición de la notación O hace que, en una

función G con complejidad O(G), todas las funciones de la forma C · G (en las que C es una

constante) pertenecen también a O(G). Por lo tanto, se habla de complejidad O(N), por ejemplo,
9

pero no de complejidad O(2 · N), ya que asintóticamente son equivalentes según la definición.

Así, por ejemplo, N pertenece a O(N) y 2 · N también pertenece a O(N).

La tabla 1 muestra las complejidades algorítmicas más importantes.

Es importante destacar que la notación O nos permite establecer un hito superior del

comportamiento de un algoritmo F. Es evidente que se pueden encontrar infinitas funciones G de

manera que se cumpla que F es de orden O(G). Por ejemplo, si un algoritmo tiene una

complejidad temporal T(N) = 2N2 + N, se puede decir que T(N) es de orden O(N2 ), pero

también O(N3 ). Sin embargo, el hecho de decir que T(N) es de orden O(N2 ) aporta mucha más

información que O(N3 ). Las complejidades T(N) que son combinaciones de potencias de N,

como la cuadrática o la cúbica, se denominan polinómicas, y son el umbral de lo que hoy se

considera computacionalmente tratable.

Comparación de complejidades

Es posible hacerse una idea del coste real que representa tener o no disponible un

algoritmo con una complejidad limitada a medida que la dimensión del problema va creciendo.

La tabla 2 muestra el tiempo proporcional (por ejemplo, en segundos) que necesita un algoritmo

según la medida de la entrada y de su complejidad.


10

Multiplicar la medida del problema por un orden de magnitud tiene un incremento muy

diferente dependiendo de la complejidad del algoritmo. Con la potencia de los superordenadores

actuales –que pueden ejecutar casi 1014 operaciones en un segundo, incluso con una medida de

sólo N = 100–, un algoritmo con complejidad exponencial no se puede resolver en un tiempo

razonable, ya que se necesitarían 1016 segundos o, lo que es lo mismo, 317 millones de años.

En general, los algoritmos con complejidad exponencial son computacionalmente

intratables según los estándares actuales, y no se pueden tratar directamente a partir de

mecanismos basados en la fuerza bruta que prueban todas las combinaciones posibles para llegar

a la solución deseada, sino que es necesario utilizar algoritmos que, a partir de una solución

aproximada, obtienen una solución más buena (o incluso óptima) a partir de técnicas

aproximadas o heurísticas.
11

Propiedades de la notación O

La primera propiedad, ya comentada, es que el orden de cualquier función de la forma

O(k · g) en la que k es una constante es O(g); es decir, sea cual sea la función de crecimiento

según el parámetro de entrada, su complejidad crece proporcionalmente a g.

Usando la definición de la notación O, vemos también que O(g1 + g2) es O(máx(g1,g2)).

Es decir, si un algoritmo G tiene dos o más subalgoritmos que se ejecutan secuencialmente sobre

el mismo conjunto de entrada, la complejidad (temporal o espacial) de G será la misma que la del

subalgoritmo que presente la complejidad (o función g) más elevada. En otras palabras, si un

algoritmo realiza dos tareas, la tarea que tenga un comportamiento más costoso es la que
12

determinará la complejidad total del algoritmo. El mismo criterio se puede aplicar al caso de la

estructura de control alternativa, tal y como se ha comentado.

Eso significa que, en general, si un algoritmo se puede descomponer en varias partes, y

una de ellas tiene una complejidad algorítmica superior al resto, la complejidad del algoritmo

quedará determinada por esta parte. Por ejemplo, si un algoritmo de búsqueda intenta ordenar los

datos de entrada con un algoritmo O(N2 ) o O(N log N) para aplicarle después una búsqueda

dicotómica –que es más eficiente que la búsqueda secuencial (O(log N) de la búsqueda

dicotómica delante de O(N) de la búsqueda secuencial)–, el resultado final es peor que si se

hiciese la búsqueda secuencial directamente, ya que la complejidad del algoritmo de ordenación

es superior

Del mismo modo –y hablando de la complejidad algorítmica de los tipos abstractos de

datos–, la complejidad de un TAD dependerá de las operaciones disponibles, su implementación

y la complejidad resultante; por lo cual, un TAD que sea eficiente para unas operaciones puede

no serlo para las otras. Por lo tanto, dependiendo del tipo de operaciones que sea necesario

ejecutar más a menudo, habrá que escoger los algoritmos y las implementaciones de cada una de

las operaciones en función de las necesidades. Así, en el ejemplo anterior, si sobre un conjunto

grande de datos se realizan muchas búsquedas, sí que puede ser interesante ordenarlo una vez,

aunque sea costoso, y reducir el coste global de las operaciones de búsqueda.

Complejidad algorítmica de los tipos abstractos de datos

En el caso concreto de los tipos abstractos de datos, cuando se habla de complejidad

algorítmica es interesante relacionar los conceptos de implementación, eficiencia y complejidad.


13

El objetivo es ser capaces de elegir el tipo de contenedor más adecuado para una cierta colección

de objetos en función de ciertas restricciones temporales y espaciales.

La idea básica es que cada TAD tiene una complejidad conocida en función de su

implementación. De hecho, se indica la complejidad de cada una de las operaciones que ofrece el

TAD. Así, por ejemplo, en la implementación de los números naturales usando el tipo int de Java

que ya conocemos, las operaciones de predecesor y sucesor de un número natural son ambas de

orden O(1); es decir, que se hacen en tiempo constante independientemente del número natural

que se manipula. Eso puede parecer muy eficiente (y, de hecho, lo es), pero es necesario tener en

cuenta que la representación de los números naturales utilizando el tipo entero de Java limita el

rango posible de números representados, lo que puede no ser válido para resolver algún

problema en el que haga falta manipular números naturales muy grandes. Por lo tanto, es posible

que la representación interna más eficiente no sea siempre válida o esté limitada a un cierto

tamaño de problema.

Complejidad del TAD de los números naturales

Para demostrar este hecho, podemos utilizar el ejemplo del TAD que implementa los

números naturales, donde se pueden encontrar dos implementaciones diferentes: una primera que

hace servir el tipo int de Java –en el que el número natural se almacena directamente por su

valor–, y una segunda implementación que usa un vector de elementos booleanos –en los que

cada número natural N se representa por un conjunto de elementos en los que los N primeros

elementos son ‘cierto’ y el resto son ‘falso’. A pesar de que este elemento está lejos de ser

realista, permite una primera comparación de las complejidades de las dos implementaciones.
14

En principio, la implementación utilizando un int resulta ideal: la complejidad espacial es

O(1), y la complejidad temporal de todos los métodos es también O(1); ya que se ejecutan en un

tiempo constante, independientemente del tamaño (la magnitud, en este caso) del número natural

representado. Podríamos decir que la eficiencia de esta implementación es perfecta.

En cambio, la representación basada en un vector de booleanos presenta una eficiencia

menor: la complejidad espacial es O(N) –ya que el espacio necesario crece linealmente con la

magnitud del número natural representado– y, por lo que respecta a la complejidad temporal, los

métodos pred() y succ() tienen una complejidad O(N), –ya que es necesario recorrer todos los

elementos del vector hasta encontrar la posición de lo que se representa. Lo mismo sucede en el

resto de métodos: la causa de esta complejidad temporal es la necesidad de ejecutar un bucle

dentro del método buscarUltimaPosicion() y duplicarVector().

Complejidad del TAD Conjunto

En este caso, un conjunto de N elementos se representa mediante un vector de al menos

N posiciones de tipo Objeto; por lo tanto, su complejidad espacial será O(N). Por lo que respecta

a la complejidad temporal, la tabla 3 muestra el resultado a partir de la implementación de cada

una de las operaciones disponibles.


15

Descripción de los Algoritmos con su Referencia

Algoritmo de ordenamiento. En computación y matemáticas un algoritmo de

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. Los 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, Bubble Sort fue analizado desde 1956. 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, como

notació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.

Clasificación

Los algoritmos de ordenamiento se pueden clasificar de las siguientes maneras:


16

1. La más común es clasificar según el lugar donde se realice la ordenación

 Algoritmos de ordenamiento interno: en la memoria del ordenador.

 Algoritmos de ordenamiento externo: en un lugar externo como un disco duro.

2. Por el tiempo que tardan en realizar la ordenación, dadas entradas ya ordenadas o

inversamente ordenadas:

 Algoritmos de ordenación natural: Tarda lo mínimo posible cuando la entrada está

ordenada.

 Algoritmos de ordenación no natural: Tarda lo mínimo posible cuando la entrada

está inversamente ordenada.

3. Por estabilidad: un ordenamiento estable mantiene el orden relativo que tenían

originalmente los elementos con claves iguales. Por ejemplo, si una lista ordenada por

fecha se reordena en orden alfabético con un algoritmo estable, todos los elementos

cuya clave alfabética sea la misma quedarán en orden de fecha. Otro caso sería

cuando no interesan las mayúsculas y minúsculas, pero se quiere que si una clave

aBC estaba antes que AbC, en el resultado ambas claves aparezcan juntas y en el

orden original: aBC, AbC. Cuando los elementos son indistinguibles (porque cada

elemento se ordena por la clave completa) la estabilidad no interesa. Los algoritmos

de ordenamiento que no son estables se pueden implementar para que sí lo sean. Una

manera de hacer esto es modificar artificialmente la clave de ordenamiento de modo

que la posición original en la lista participe del ordenamiento en caso de coincidencia.

Los algoritmos se distinguen por las siguientes características:


17

Complejidad computacional (peor caso, caso promedio y mejor caso) en términos de n, el

tamaño de la lista o arreglo. Para esto se usa el concepto de orden de una función y se usa la

notación O(n). El mejor comportamiento para ordenar (si no se aprovecha la estructura de las

claves) es O(n log n). Los algoritmos más simples son cuadráticos, es decir O(n²). Los

algoritmos que aprovechan la estructura de las claves de ordenamiento (p. ej. bucket sort) pueden

ordenar en O(kn) donde k es el tamaño del espacio de claves. Como dicho tamaño es conocido a

priori, se puede decir que estos algoritmos tienen un desempeño lineal, es decir O(n).

Uso de memoria y otros recursos computacionales. También se usa la notación O(n).

Estabilidad

Los algoritmos de ordenamiento estable mantienen un relativo preorden total. Esto

significa que un algoritmo es estable solo cuando hay dos registros R y S con la misma clave y

con R apareciendo antes que S en la lista original.

Cuando elementos iguales (indistinguibles entre sí), como números enteros, o más

generalmente, cualquier tipo de dato en donde el elemento entero es la clave, la estabilidad no es

un problema. De todas formas, se asume que los siguientes pares de números están por ser

ordenados por su primer componente:

(4, 1) (3, 7) (3, 1) (5, 6)

En este caso, dos resultados diferentes son posibles, uno de los cuales mantiene un orden

relativo de registros con claves iguales, y una en la que no:


18

(3, 7) (3, 1) (4, 1) (5, 6) (orden mantenido).

(3, 1) (3, 7) (4, 1) (5, 6) (orden cambiado).

Los algoritmos de ordenamiento inestable pueden cambiar el orden relativo de registros

con claves iguales, pero los algoritmos estables nunca lo hacen. Los algoritmos inestables

pueden ser implementados especialmente para ser estables. Una forma de hacerlo es extender

artificialmente el cotejamiento de claves, para que las comparaciones entre dos objetos con

claves iguales sean decididas usando el orden de las entradas original. Recordar este orden entre

dos objetos con claves iguales es una solución poco práctica, ya que generalmente acarrea tener

almacenamiento adicional.

Ordenar según una clave primaria, secundaria, terciara, etc., puede ser realizado

utilizando cualquier método de ordenamiento, tomando todas las claves en consideración (en

otras palabras, usando una sola clave compuesta). Si un método de ordenamiento es estable, es

posible ordenar múltiples ítems, cada vez con una clave distinta. En este caso, las claves

necesitan estar aplicadas en orden de aumentar la prioridad. Ejemplo: ordenar pares de números,

usando ambos valores.

(4, 1) (3, 7) (3, 1) (4, 6) (original)

(4, 1) (3, 1) (4, 6) (3, 7) (después de ser ordenado por el segundo valor)

(3, 1) (3, 7) (4, 1) (4, 6) (después de ser ordenado por el primer valor)
19

Por otro lado: (3, 7) (3, 1) (4, 1) (4, 6) (después de ser ordenado por el primer valor)

(3, 1) (4, 1) (4, 6) (3, 7) (después de ser ordenando por el segundo valor, el

orden por el primer valor es perturbado)

Sort Burbuja – Pseudocódigo

Algoritmo de ordenamiento. 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.

El procedimiento de la burbuja es el siguiente: § Ir comparando desde la casilla 0 número

tras número hasta encontrar uno mayor, si este es realmente el mayor de todo el vector se llevará

hasta la última casilla, si no es así, será reemplazado por uno mayor que él. § Este procedimiento

seguirá así hasta que haya ordenado todas las casillas del vector. § Una de las deficiencias del

algoritmo es que ya cuando a ordenado parte del vector vuelve a compararlo cuando esto ya no

es necesario.

Dado un vector a1, a2, a3... an 1) Comparar a1 con a2 e intercambiarlos si a1>a2 (o a12)

2. Seguir hasta que todo se haya comparado an-1 con an 3) Repetir el proceso anterior n-1 veces

Algoritmo: Complejidad for(i=0; i < n-++){ T(n2)


20

Quicksort – Pseudocódigo

QuickSort (en inglés, ordenamiento rápido). Es un algoritmo 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:

1. Elegir un elemento de la lista de elementos a ordenar, al que llamaremos pivote.

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


21

la implementación deseada. En este momento, el pivote ocupa exactamente el lugar

que le corresponderá en la lista ordenada.

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

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

Eficiencia del Algoritmo

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). Y no es extraño, pues,

que la mayoría de optimizaciones que se aplican al algoritmo se centren en la elección del pivote.

Bucket Sort – Pseudocódigo

Análisis Comparativo

Conclusiones

Bibliografía
22

 Wikipedia.
 Explicación de los distintos métodos de ordenamiento en
Java. (pdf)
 Discusión sobre varios algoritmos de ordenación y sus
características. (licencia GFDL) (pdf)
 Animación de algoritmos de ordenamient.
 Animación de algoritmos de ordenamiento. (en inglés)
 ALT: Algorithm Learning Tool. Herramienta de apoyo a la
enseñanza de algoritmos que muestra gráficamente su
funcionamiento. Permite implementar algoritmos propios y
realizar una ejecución dinámica e interactiva.
 Códigos de Ordenamiento en Python.
 Estructuras de datos.
 https://www.mclibre.org/

 https://docs.python.org/3/

 WIRTH, Niklaus. Algoritmos y Estructuras de Datos. Pentice


Hall, 1987.
 WEISS, M. A., Estructuras de datos y algoritmos. Addison-
Wesley Iberoamericana, 1995.
 WEISS, M. A., Estructuras de datos y algoritmos. Addison-
Wesley Iberoamericana, 1995.
 Curso de programación II, Universidad de Ciencias
Informáticas.
 https://www2.infor.uva.es/~jvalvarez/docencia/tema5.pdf

 https://www.cs.us.es/~jalonso/cursos/i1m-19/temas/tema-28.html

 http://uoc.gitlab.io/2010/EI/ei2.pdf

 https://repository.icesi.edu.co/biblioteca_digital/bitstream/10906/85554/1/

T01842.pdf

 http://uoc.gitlab.io/2010/EI/ei2.pdf

También podría gustarte