La recursividad es más intuitivo, por lo tanto prefiero el mismo, excepto en algunas situaciones en las que quiero evitar una profundidad significativa de la pila (por ejemplo, mientras se consumen ciertas implementaciones de co-rutina). Sin embargo, en el caso de Merge sort, la versión iterativa es realmente más fácil de seguir (al menos el pseudo código).
Todo lo que se necesita es un bucle anidado con el bucle interno realizando fusiones en pares de 2^k elementos con el bucle externo responsable de incrementar k.
Un paso adicional que se requiere es unir cualquier grupo no emparejado con el grupo fusionado anterior. Se encontrará un grupo desapareado si la cantidad de elementos no es una potencia de 2. Un grupo no emparejado siempre estará al final de la iteración.
p. Ej. [5, 7, 3, 4, 1, 9] -> [5, 7] [3, 4] [1, 9] -> [3, 4, 5, 7] [1, 9] -> [ 1, 3, 4, 5, 7, 9]
En el ejemplo anterior [1, 9] hay un grupo que no tenía otro grupo para fusionarse inicialmente. Por lo tanto, se fusionó con el grupo anterior (que se había fusionado y ya ordenados)
Aquí es una implementación de Python:
from MergeSort import merge
def sort(arr):
n = len(arr) - 1
c = 1
start = 0
mid = 0
end = 0
while c <= n:
while end < n:
mid = start + c//2
end = start + c
if (start < n) and (end <= n):
merge(arr, start, mid, end)
start = end + 1
else:
merge(arr, start - c - 1, start-1, n)
c = 2*c + 1
start = 0
mid = 0
end = 0
he utilizado la función de combinación de la versión normal (recursivo). Si bien el código anterior no es el más elegante, pero funciona y tiene la misma complejidad que la versión recursiva.(No he comprobado a fondo, pero parece por lo que a mí de un vistazo rápido)
Aquí es una prueba de unidad:
def test_merge_sort_iterative(self):
for i in range(1, 100):
length = randint(10, 5000)
data = [randint(1, 10000) for x in range(1, length)]
IterativeMergeSort.sort(data)
issorted = True
i = 0
while (i < len(data) - 1) & issorted:
if data[i] > data[i + 1]:
issorted = False
i += 1
self.assertTrue(issorted, data)
return
Considerar las respuestas aquí: http://stackoverflow.com/questions/2171517/ implement-a-mergesort-without-using-an-additional-array – Marcin