2013-09-28 06:12:19 +02:00
|
|
|
|
|
|
|
from random import randint
|
|
|
|
from time import clock
|
2013-10-03 05:36:40 +02:00
|
|
|
from sys import argv
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2013-10-03 05:36:40 +02:00
|
|
|
class SortAlgorithm(object):
|
2015-11-13 02:42:25 +01:00
|
|
|
def __init__(self):
|
|
|
|
self.swaps = 0
|
|
|
|
self.vgls = 0
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2015-11-13 02:42:25 +01:00
|
|
|
def sort(self,a):
|
|
|
|
raise Exception("Fail")
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2015-11-13 02:42:25 +01:00
|
|
|
def swap(self,a,i,j):
|
|
|
|
self.swaps += 1
|
|
|
|
a[i],a[j] = a[j],a[i]
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2015-11-13 02:42:25 +01:00
|
|
|
def set(self,a,i,v):
|
|
|
|
self.swaps += 1
|
|
|
|
a[i] = v
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2015-11-13 02:42:25 +01:00
|
|
|
def vgl(self,b):
|
|
|
|
self.vgls += 1
|
|
|
|
return b
|
2013-09-28 06:12:19 +02:00
|
|
|
|
|
|
|
class BubbleSort(SortAlgorithm):
|
2015-11-13 02:42:25 +01:00
|
|
|
def sort(self,a):
|
|
|
|
n = len(a)
|
|
|
|
swapped = True
|
|
|
|
while swapped and n > 1:
|
|
|
|
swapped = False
|
|
|
|
for i in range(0,n-1):
|
|
|
|
if self.vgl(a[i] > a[i+1]):
|
|
|
|
self.swap(a,i,i+1)
|
|
|
|
swapped = True
|
|
|
|
n-=1
|
|
|
|
return a
|
2013-09-28 06:12:19 +02:00
|
|
|
|
|
|
|
class InsertSort(SortAlgorithm):
|
2015-11-13 02:42:25 +01:00
|
|
|
def sort(self,a):
|
|
|
|
for i in range(1,len(a)):
|
|
|
|
t = a[i]
|
|
|
|
j = i-1
|
|
|
|
while j >= 0 and self.vgl(a[j] > t):
|
|
|
|
self.set(a,j,a[j+1])
|
|
|
|
j-=1
|
|
|
|
#a[j+1] = t
|
|
|
|
self.set(a, j+1, t)
|
|
|
|
return a
|
2013-09-28 06:12:19 +02:00
|
|
|
|
|
|
|
class QuickSort(SortAlgorithm):
|
2015-11-13 02:42:25 +01:00
|
|
|
def sort(self,a):
|
|
|
|
self.qsort(a, 0, len(a)-1)
|
|
|
|
return a
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2015-11-13 02:42:25 +01:00
|
|
|
def qsort(self,a, left, right):
|
|
|
|
if left < right:
|
|
|
|
pivot = self.seperate(a, left, right)
|
|
|
|
self.qsort(a, left, pivot - 1)
|
|
|
|
self.qsort(a, pivot+1, right)
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2015-11-13 02:42:25 +01:00
|
|
|
def seperate(self, a, left, right):
|
|
|
|
i = left
|
|
|
|
j = right-1
|
|
|
|
pivot = a[right]
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2015-11-13 02:42:25 +01:00
|
|
|
while i < j:
|
|
|
|
while self.vgl(a[i] <= pivot) and i < right: i+=1
|
|
|
|
while self.vgl(a[j] >= pivot) and j > left: j-=1
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2015-11-13 02:42:25 +01:00
|
|
|
if i < j:
|
|
|
|
self.swap(a,i,j)
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2015-11-13 02:42:25 +01:00
|
|
|
if a[i] > pivot:
|
|
|
|
self.swap(a,i,right)
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2015-11-13 02:42:25 +01:00
|
|
|
return i
|
2013-09-28 06:12:19 +02:00
|
|
|
|
|
|
|
class HeapSort(SortAlgorithm):
|
2015-11-13 02:42:25 +01:00
|
|
|
def sort(self,a):
|
|
|
|
self.heapsort(a)
|
|
|
|
return list(reversed(a))
|
|
|
|
|
|
|
|
def heapify(self, data, i, w):
|
|
|
|
#indexes = filter(lambda v: v < w, [i,2*(i+1)-1,2*(i+1)])
|
|
|
|
#largest = max(indexes,key=lambda v: data[v])
|
|
|
|
r = 2*(i+1)
|
|
|
|
l = r-1
|
|
|
|
largest = i
|
|
|
|
if l < w and self.vgl(data[l] < data[largest]):
|
|
|
|
largest = l
|
|
|
|
if r < w and self.vgl(data[r] < data[largest]):
|
|
|
|
largest = r
|
|
|
|
if largest != i:
|
|
|
|
self.swap(data,i,largest)
|
|
|
|
self.heapify(data, largest, w)
|
|
|
|
|
|
|
|
def build_heap(self, data):
|
|
|
|
w = len(data)
|
|
|
|
i = int(w/2-1)
|
|
|
|
while i>=0:
|
|
|
|
self.heapify(data, i, w)
|
|
|
|
i-=1
|
|
|
|
|
|
|
|
def heapsort(self,data):
|
|
|
|
self.build_heap(data)
|
|
|
|
i = len(data)-1
|
|
|
|
while i > 0:
|
|
|
|
self.swap(data,i,0)
|
|
|
|
self.heapify(data, 0, i)
|
|
|
|
i-=1
|
2013-09-28 06:12:19 +02:00
|
|
|
|
|
|
|
class MergeSort(SortAlgorithm):
|
2015-11-13 02:42:25 +01:00
|
|
|
def sort(self, a):
|
|
|
|
return self.mergesort(a)
|
|
|
|
|
|
|
|
def mergesort(self,a):
|
|
|
|
if len(a) <= 1:
|
|
|
|
return a
|
|
|
|
else:
|
|
|
|
n = int(len(a)/2);
|
|
|
|
return self.merge(self.mergesort(a[:n] or []), self.mergesort(a[n:] or []))
|
|
|
|
|
|
|
|
def merge(self,a,b):
|
|
|
|
l = []
|
|
|
|
while True:
|
|
|
|
if len(a) == 0:
|
|
|
|
l += b
|
|
|
|
break
|
|
|
|
if len(b) == 0:
|
|
|
|
l += a
|
|
|
|
break
|
|
|
|
|
|
|
|
if self.vgl(a[0] < b[0]):
|
|
|
|
l.append(a[0])
|
|
|
|
a = a[1:]
|
|
|
|
else:
|
|
|
|
l.append(b[0])
|
|
|
|
b = b[1:]
|
|
|
|
self.swaps+=1
|
|
|
|
return l
|
2013-09-28 06:12:19 +02:00
|
|
|
|
|
|
|
class ShellSort(SortAlgorithm):
|
2015-11-13 02:42:25 +01:00
|
|
|
def sort(self,a):
|
|
|
|
spalten = [2147483647, 1131376761, 410151271, 157840433, 58548857, 21521774, 8810089, 3501671, 1355339, 543749, 213331,
|
|
|
|
84801, 27901, 11969, 4711, 1968, 815, 271, 111, 41, 13, 4, 1]
|
|
|
|
|
|
|
|
for k in range(0,23):
|
|
|
|
h = spalten[k]
|
|
|
|
for i in range(h,len(a)):
|
|
|
|
t = a[i]
|
|
|
|
j = i
|
|
|
|
while j>=h and self.vgl(a[j-h]>t):
|
|
|
|
#a[j] = a[j-h]
|
|
|
|
self.swap(a,j,j-h)
|
|
|
|
j-=h
|
|
|
|
a[j] = t
|
|
|
|
return a
|
2013-09-28 06:12:19 +02:00
|
|
|
|
|
|
|
class SelectSort(SortAlgorithm):
|
2015-11-13 02:42:25 +01:00
|
|
|
def sort(self,a):
|
|
|
|
n = len(a)
|
|
|
|
left = 0
|
|
|
|
while left < n:
|
|
|
|
m = left
|
|
|
|
for i in range(left,n):
|
|
|
|
if self.vgl(a[i] < a[m]):
|
|
|
|
m = i
|
|
|
|
self.swap(a,m,left)
|
|
|
|
left+=1
|
|
|
|
return a
|
2013-09-28 06:12:19 +02:00
|
|
|
|
|
|
|
class SortTester:
|
2015-11-13 02:42:25 +01:00
|
|
|
def __init__(self, algorithms):
|
|
|
|
self.algorithms = algorithms
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2015-11-13 02:42:25 +01:00
|
|
|
def test(self, size=1000):
|
|
|
|
results = {}
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2015-11-13 02:42:25 +01:00
|
|
|
data = list([ randint(0, size) for i in range(0,size) ])
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2015-11-13 02:42:25 +01:00
|
|
|
for algorithm in self.algorithms:
|
|
|
|
print("Testing %s..." % algorithm.__name__)
|
|
|
|
inst = algorithm()
|
|
|
|
c = data[:]
|
|
|
|
s = inst.sort(c)
|
|
|
|
if not SortedTest().test(s):
|
|
|
|
raise Exception(algorithm.__name__+" failed to sort")
|
|
|
|
results[algorithm] = (inst.vgls,inst.swaps)
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2015-11-13 02:42:25 +01:00
|
|
|
return results
|
2013-09-28 06:12:19 +02:00
|
|
|
|
2013-10-03 05:36:40 +02:00
|
|
|
class SortedTest:
|
2015-11-13 02:42:25 +01:00
|
|
|
def test(self, a):
|
|
|
|
v = a[0]
|
|
|
|
for n in a[1:]:
|
|
|
|
if v > n:
|
|
|
|
return False
|
|
|
|
v = n
|
|
|
|
return True
|
2013-10-03 05:36:40 +02:00
|
|
|
|
2013-09-28 06:12:19 +02:00
|
|
|
def main():
|
2015-11-13 02:42:25 +01:00
|
|
|
try:
|
|
|
|
size = int( argv[1])
|
|
|
|
except Exception:
|
|
|
|
size= 1000
|
|
|
|
result = SortTester(list( SortAlgorithm.__subclasses__() )).test(size=size)
|
|
|
|
for cls, r in sorted(result.items(),key=lambda e: e[1][0]+e[1][1]):
|
|
|
|
print("%-12s: %10d, %10d compares, %10d swaps" % (cls.__name__, r[0]+r[1], r[0],r[1]))
|
2013-09-28 06:12:19 +02:00
|
|
|
|
|
|
|
def test():
|
2015-11-13 02:42:25 +01:00
|
|
|
print(HeapSort().sort([randint(0,500) for i in range(0,100)]))
|
2013-09-28 06:12:19 +02:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2015-11-13 02:42:25 +01:00
|
|
|
main()
|