Rekurencja jest bardziej intuicyjne stąd wolę takie same z wyjątkiem niektórych sytuacjach, kiedy chcemy uniknąć znacząca głębokość stosu (np. podczas konsumowania pewnych implementacji rutynowych). W przypadku sortowania Merge iteratywna wersja jest jednak łatwiejsza do śledzenia (przynajmniej pseudo kod).
Wszystko, co jest potrzebne, to zagnieżdżona pętla z wykonaniem wewnętrznej pętli scala na pary 2^k elementów z zewnętrzną pętlą odpowiedzialną za inkrementację k.
Dodatkowym krokiem, który jest wymagany, jest scalenie niesparowanej grupy z poprzednią scaloną grupą. Niesparowana grupa zostanie napotkana, jeśli liczba elementów nie jest potęgą 2. Niesparowana grupa zawsze znajdzie się na końcu iteracji.
np. [5, 7, 3, 4, 1, 9] -> [5, 7] [3, 4] [1, 9] -> [3, 4, 5, 7] [1, 9] -> [ 1,3,4,5, 7,9). W ten sposób została połączona z poprzedniej grupy (które zostały połączone i sortowanych już)
Oto implementacja Pythona:
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
użyłem funkcji scalania od zwykłego (rekurencyjne) wersji. Chociaż powyższy kod nie jest najbardziej elegancki, ale działa i ma taką samą złożoność, jak wersja rekursywna.(Ja dokładnie nie sprawdził, ale wydaje się tak do mnie z szybkim spojrzeniem)
Tutaj jest test jednostki:
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
Rozważmy odpowiedź tutaj: http://stackoverflow.com/questions/2171517/ Implementowanie-a-mergesort-bez-używania-dodatkowej tablicy – Marcin