/* put the smallest element at the front of the current list
call selection on the list minus the smallest element */
/* remove the first occurance of atom A from L */
list<int> remove(list<int> lis, int item) {
if (lis.size() == 0)
return lis;
else if (*lis.begin() == item) {
lis.pop_front();
return lis;
}
else {
int first = *lis.begin();
lis.pop_front();
list<int> removedList = remove(lis, item);
removedList.push_front(first);
return removedList;
}
}
/* looks for the smallest element in the list
atom A is the current smallest */
int smallest(list<int> lis, int small) {
if (lis.size() == 0)
return small;
else if (*lis.begin() < small) {
int first = *lis.begin();
lis.pop_front();
return smallest(lis, first);
} else {
lis.pop_front();
return smallest(lis, small);
}
}
list<int> selectionsort(list<int> lis) {
if (lis.size() == 0) return lis;
else {
int first = *lis.begin();
list<int> rest = lis;
rest.pop_front();
int s = smallest(rest, first);
list<int> sortedList = selectionsort(remove(lis,s));
sortedList.push_front(s);
return sortedList;
}
}
(mergesort '(6 4 5 7 8 9 3 4))
/ \
(mergesort '(6 4 5 7)) (mergesort '(8 9 3 4))
/ \ / \
(mergesort '(6 4)) (mergesort '(5 7)) (mergesort '(8 9)) (mergesort '(3 4))
At the lowest tree leves, the two element get sorted and the recursion unwinds.
(mergesort '(6 4 5 7 8 9 3 4))
/ \
(mergesort '(6 4 5 7)) (mergesort '(8 9 3 4))
/ \ / \
(4 6) (5 7) (8 9)) (3 4))
The next level of recursion:
(mergesort '(6 4 5 7 8 9 3 4))
/ \
(4 5 6 7)) (3 4 8 9)
/ \ / \
(4 6) (5 7) (8 9)) (3 4))
And the final level with merges into the overall list
(3 4 4 5 6 7 8 9)
/ \
(4 5 6 7) (3 4 8 9)
Of course, this is not the actual order that things happen but it give
the overall algorithm flavor.
In scheme, we can write functions to split lists, and merge sorted
lists. Once we have these, the mergesort itself is fairly short.
NOT YET IMPLEMENTED IN CPP def mergesort(lis) if lis.length == 0 then [] elsif lis.length == 1 then lis elsif lis.length == 2 then mergelists ([lis[0]], lis[1..lis.length-1]) else mergelists(mergesort(split(lis)[0]),mergesort(split(lis)[1..lis.length-1][0])) end end def mergelists(lis, m) # assume L and M are sorted lists if lis.length==0 then m elsif m.length==0 then lis elsif lis[0] < m[0] then [lis[0]] + mergelists(lis[1..lis.length-1], m) else [m[0]] + mergelists(lis, m[1..m.length-1]) end end def sub(lis, start, stop, ctr) # extract elements start to stop into a list if lis.length== 0 then lis elsif ctr < start then sub(lis[1..lis.length-1], start, stop, ctr+1) elsif ctr > stop then [] else [lis[0]] + sub(lis[1..lis.length-1],start, stop, ctr+1) end end def split(lis) # split the list in half:, ; returns ((first half)(second half)) len=lis.length if len == 0 then [lis]+[lis] elsif len == 1 then [lis] + [[]] else [sub(lis, 1, len//2, 1)] + [sub(lis, (len//2)+1, len, 1)] end end
; We are going to represent each node in a binary tree as:
; (value (left child)(right child)) If the node has no left
; and/or right child, this is represented with (). So,
; (2 (1()())(3()())) is the tree: 2
; / \
; 1 3
(define (binarysort L)
(if (null? L) '()
(traverse (btree L))
))
(define (btree L)
(if (= (length L) 1) (leaf (car L))
(binsert (btree (cdr L)) (car L))
)
)
(define (binsert T A) ; insert A into the tree
(cond ( (null? T) (leaf A) ) ; insert here
( (> (car T) A) (list (car T)
(binsert (car (cdr T)) A)
(car (cdr (cdr T))))
) ; left subtree
( else (list (car T)
(car (cdr T))
(binsert (car (cdr (cdr T))) A)) ; right subtree
)
)
)
(define (leaf A) ; add a leaf to the tree (A ()())
(list A '() '())
)
(define (traverse L) ; output sorted list by traversing the tree
(cond ( (null? L) L)
( else
(append (traverse (car (cdr L)))
(cons (car L)(traverse (car (cdr (cdr L))))))
)
)
)
(define (length L)
(if (null? L) 0
(+ 1 (length (cdr L)))
)
)