Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libsortvis/algos/bitonicsort.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
def compare(lst, i, j, dir):
if dir == (lst[i] > lst[j]):
lst[i], lst[j] = lst[j], lst[i]
lst.log()
# lst.log()


def merge(lst, lo, n, dir):
Expand Down
2 changes: 1 addition & 1 deletion libsortvis/algos/bubblesort.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def bubblesort(lst):
for j in range(bound):
if lst[j] > lst[j+1]:
lst[j], lst[j+1] = lst[j+1], lst[j]
lst.log()
# lst.log()
t = j
if t == 0:
break
Expand Down
4 changes: 2 additions & 2 deletions libsortvis/algos/cocktailsort.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def cocktailsort(lst):
for i in xrange(begin, end):
if lst[i] > lst[i + 1]:
lst[i], lst[i + 1] = lst[i + 1], lst[i]
lst.log()
# lst.log()
finished = False
if finished:
break
Expand All @@ -16,7 +16,7 @@ def cocktailsort(lst):
for i in reversed(xrange(begin, end)):
if lst[i] > lst[i + 1]:
lst[i], lst[i + 1] = lst[i + 1], lst[i]
lst.log()
# lst.log()
finished = False
begin += 1

2 changes: 1 addition & 1 deletion libsortvis/algos/combsort.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def combsort(lst):
for i in xrange(len(lst) - gap):
if lst[i] > lst[i + gap]:
lst[i], lst[i + gap] = lst[i + gap], lst[i]
lst.log()
# lst.log()
swaps = True
if not swaps and gap <= 1:
break
Expand Down
2 changes: 1 addition & 1 deletion libsortvis/algos/gnomesort.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def gnomesort(lst):
i += 1
else:
lst[i], lst[i - 1] = lst[i - 1], lst[i]
lst.log()
# lst.log()
i -= 1


4 changes: 2 additions & 2 deletions libsortvis/algos/heapsort.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def sift(lst, start, count):
child += 1
if lst[root] < lst[child]:
lst[root], lst[child] = lst[child], lst[root]
lst.log()
# lst.log()
root = child
else:
return
Expand All @@ -20,6 +20,6 @@ def heapsort(lst):
start -= 1
while end > 0:
lst[end], lst[0] = lst[0], lst[end]
lst.log()
# lst.log()
sift(lst, 0, end)
end -= 1
2 changes: 1 addition & 1 deletion libsortvis/algos/insertionsort.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ def insertionsort(lst):
if lst[i] < lst[j]:
x = lst.pop(i)
lst.insert(j, x)
lst.log()
# lst.log()
2 changes: 1 addition & 1 deletion libsortvis/algos/mergesort.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ def mergesort(lst, left=0, right=None):
i += 1
continue
lst[i], lst[i+1:j+1] = lst[j], lst[i:j]
lst.log()
# lst.log()
i, end_i, j = i + 1, end_i + 1, j + 1
2 changes: 1 addition & 1 deletion libsortvis/algos/oddevensort.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def oddevensort(lst, nloops=2):
for i in xrange(n, len(lst) - 1, nloops):
if lst[i] > lst[i + 1]:
lst[i], lst[i + 1] = lst[i + 1], lst[i]
lst.log()
# lst.log()
finished = False


10 changes: 5 additions & 5 deletions libsortvis/algos/quicksort.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@

# note: quicksort does unnecessary comparisons of elements with the same index
def quicksort(lst, left=0, right=None):
if right is None:
right = len(lst) - 1
l = left
r = right
if l <= r:
if l <= r: # why not < ?
mid = lst[(left+right)/2]
while l <= r:
while l <= r: # why not < ?
while l <= right and lst[l] < mid:
l += 1
while r > left and lst[r] > mid:
r -= 1
if l <= r:
lst[l], lst[r] = lst[r], lst[l]
if l != r:
lst.log()
# if l != r:
# lst.log()
l+=1
r-=1
if left < r:
Expand Down
4 changes: 2 additions & 2 deletions libsortvis/algos/radixsort.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ def radixsort(lst):
for j, item in enumerate(chain(zeroes, orig, ones)):
lst[j] = item
# for a more simple graph, comment out the line below
lst.log()
# lst.log()
#
if is_sorted(lst):
return
lst.log()
# lst.log()
shift = shift << 1
zeroes[:] = []
ones[:] = []
4 changes: 2 additions & 2 deletions libsortvis/algos/selectionsort.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ def selectionsort(lst):
for j in range(len(lst)-1, -1, -1):
m = lst.index(max(lst[:j+1])) # No, this is not efficient ;)
lst[m], lst[j] = lst[j], lst[m]
if m != j:
lst.log()
# if m != j:
# lst.log()

2 changes: 1 addition & 1 deletion libsortvis/algos/shellsort.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def shellsort(lst):
flag = 1
lst[i+h], lst[i] = lst[i], lst[i+h]
i -= h
lst.log()
# lst.log()
else:
break
lst[i+h] = r
Expand Down
4 changes: 2 additions & 2 deletions libsortvis/algos/smoothsort.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def sift(lst, pshift, head):
lst[head], lst[rt] = lst[rt], lst[head]
head = rt
pshift -= 2
lst.log()
# lst.log()


def trinkle(lst, p, pshift, head, trusty):
Expand All @@ -47,7 +47,7 @@ def trinkle(lst, p, pshift, head, trusty):
if lst[rt] >= lst[stepson] or lst[lf] >= lst[stepson]:
break
lst[head], lst[stepson] = lst[stepson], lst[head]
lst.log()
# lst.log()
head = stepson
trail = trailingzeroes(p & ~1)
p >>= trail
Expand Down
2 changes: 1 addition & 1 deletion libsortvis/algos/stoogesort.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ def stoogesort(lst, i=0, j=None):
j = len(lst) - 1
if lst[j] < lst[i]:
lst[i], lst[j] = lst[j], lst[i]
lst.log()
# lst.log()
if j - i > 1:
t = (j - i + 1) // 3
stoogesort(lst, i, j - t)
Expand Down
50 changes: 27 additions & 23 deletions libsortvis/algos/timsort.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,42 @@
from ..sortable import Comparator
class TimBreak(Exception):
def __init__(self, *args):
super(TimBreak, self).__init__(*args)

class TimBreak(Exception): pass


class TimWrapper:
list = None
class TimComparator(Comparator):
comparisons = 0
limit = 0
def __init__(self, n):
self.n = n
def __init__(self, tracklist, i):
super(TimComparator, self).__init__(tracklist, i)

def __cmp__(self, other):
if TimWrapper.comparisons > TimWrapper.limit:
raise TimBreak
TimWrapper.comparisons += 1
return cmp(self.n, other.n)

def __getattr__(self, attr):
return getattr(self.n, attr)
TimComparator.comparisons += 1
if TimComparator.comparisons > TimComparator.limit:
self.tracklist.total_comparisons += 1
raise TimBreak(self, other)
return cmp(self.i, other.i)


def timsort(lst):
lst.wrap(TimWrapper)
TimWrapper.list = lst
prev = [i.n for i in lst]
# we need a hack in this one, as the TrackList.lst pointer to the list
# is set to [] while lst.sort() is running
# so what happens here is: we break each sort after limit comparisons,
# log the outcome, increase limit by 1 and run again from the beginning.
TimComparator.comparisons = 0
TimComparator.limit = 0
lst.setComparator(TimComparator, wrapOldOne=False)
TimComparator.list = lst
while 1:
TimWrapper.comparisons = 0
TimWrapper.limit += 1
TimComparator.comparisons = 0
TimComparator.limit += 1
lst.reset()
try:
lst.sort()
except TimBreak:
if prev != [i.n for i in lst]:
lst.log()
prev = [i.n for i in lst]
except TimBreak as t:
s,o = t
lst.addComparison(s,o)
lst.log()
else:
lst.log()
break

117 changes: 117 additions & 0 deletions libsortvis/quickComparisonsVis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# -*- coding: utf-8 -*-
'''
A quick & dirty demo script using scipy and matplotlib to visualize compared elements.
Created on Nov 14, 2010

@author: joern
'''

from libsortvis import graph, algos, sortable
import random
import scipy as sc
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.cm as cm

if __name__ == '__main__':
lst = range(100)
random.shuffle(lst)

verbose = True # get # of comparisons
debug = False
drawComparisons = True # mark each comparison between 2 elements with a dot on both
compress = False # only draw each column if it changed.

createGraphic = False # save output

if createGraphic:
gstart = graph.rgb("ffffff")
gend = graph.rgb("000000")
csource = graph.ColourGradient(gstart, gend)
background = graph.rgb("ffffff")
titlecolour = graph.rgb("000000")
line = 6
border = 1
titleheight = 20
rotate = False
height = (line + border + 5) * len(lst)
width = int(height * 3)
prefix = "" # file output prefix
title = ""
ldrawer = graph.Weave(
csource,
width,
height,
titleheight,
titlecolour,
background,
rotate,
line,
border
)


assert not (drawComparisons and compress), "can't show both in one image,"\
" decide if you want to show which items are compared or only show lists if they change."

todraw = ["timsort", "mergesort", "quicksort", "bubblesort", "insertionsort"]

for algo in todraw:
if verbose: print algo

track = sortable.TrackList(lst) # wrap lst with our TrackList
algos.algorithms[algo](track) # apply the sorting algorithm and sort the list
track.log() # could happen that the last comparison swaps elements, so log again

if verbose:
print "\t%s comparisons"%(track.total_comparisons)

m = []
for j in track:
m.append(j.path)
a = sc.array(m)
if compress:
prev = -1
todel = []
for i in range(a.shape[1]):
col = a[:,i]
if (col == prev).all():
if debug: print "delete column", i
todel.append(i)
prev = col
a = sc.delete(a, todel, 1)
assert (a[:,0][sc.array(lst)] == sc.array(lst)[a[:,0]]).all(), \
"first path column are does not correspond to init positions of all sorted elements"
assert (sorted(a[:,-1]) == a[:,-1]).all(), \
"last path column not sorted"
if debug: print a


plt.figure()
plt.title(algo)

# line colors
sm = cm.ScalarMappable(cmap=cm.get_cmap("hot"),
norm=colors.Normalize(vmin=0, vmax=(1/0.65)*len(lst))) # use only lower 0.65 of cm
for i,row in enumerate(a):
c = sm.to_rgba(i)
plt.plot(row, color=c)
if drawComparisons:
comps = sc.array(track.comparisonList)
plt.plot(range(1,len(track.comparisonList)+1), comps[:,0], 'o', color=(0., 0., 1.), alpha=0.5)
plt.plot(range(1,len(track.comparisonList)+1), comps[:,1], 'o', color=(1., 0., 0.), alpha=0.5)


if createGraphic:
name = prefix + algo + ".png"
ldrawer.draw(
track,
algo if title else None,
name,
)

plt.show()




Loading