Merge Sort
Each recusive call
divides the unsorted list into halves.
def merge_sort(items, depth=0):
if len(items) <= 1:
return items
m = len(items) // 2
L = merge_sort(items[:m], depth + 1)
R = merge_sort(items[m:], depth + 1)
print(depth * " ", L, " ", R)
i = 0
j = 0
sorted = []
while len(sorted) < len(items):
if L[i] < R[j]:
sorted.append(L[i])
i = i + 1
else:
sorted.append(R[j])
j = j + 1
if i == len(L):
sorted.extend(R[j:])
break
if j == len(R):
sorted.extend(L[i:])
break
print(depth * " ", sorted)
return sorted
data = [2, 9, 8, 5, 3, 4, 7, 6]
print(data)
sorted = merge_sort(data)
print(sorted)
Timer
Faster then quicksort,
almost as fast as native sort().
import random
import time
start, end = 0, 0
def timer(func):
def wrapper(*args, **kwargs):
global start, end
if start == 0:
start = time.time()
result = func(*args, **kwargs)
end = time.time()
return result
return wrapper
@timer
def merge_sort(items):
if len(items) <= 1:
return items
m = len(items) // 2
L = merge_sort(items[:m])
R = merge_sort(items[m:])
i = 0
j = 0
sorted = []
while len(sorted) < len(items):
if L[i] < R[j]:
sorted.append(L[i])
i = i + 1
else:
sorted.append(R[j])
j = j + 1
if i == len(L): sorted.extend(R[j:])
if j == len(R): sorted.extend(L[i:])
return sorted
@timer
def quicksort(items, i=0, j=None):
if j == None:
j = len(items) - 1
if i > j:
return
pivot = items[j]
for k in range(i, j + 1):
if items[k] < pivot:
items[i], items[k] = items[k], items[i]
i = i + 1
if items[k] == pivot:
items[i], items[k] = items[k], items[i]
quicksort(items, 0, i - 1)
quicksort(items, i + 1, j)
@timer
def native_sort(items):
return items.sort()
lst = random.sample(range(0, 300000), 300000)
start, end = 0, 0
merge_sort(lst); t1 = end - start
start, end = 0, 0
native_sort(lst); t2 = end - start
print("merge_sort() 300000 items:", t1, "s")
print("sort() 300000 items:", t2, "s")