! Object methodsFor: 'algorithms' !
selection
" (FileStream oldFileNamed: 'selection.st') fileIn.
numbers := #(4 3 16 1 14 25 2) asOrderedCollection.
numbers selection"
| currentsmallest |
self size = 0 ifTrue: [ ^#() asOrderedCollection.]
ifFalse: [ "put the smallest element at the front of the current list "
currentsmallest := self smallest: self first.
^(OrderedCollection with: currentsmallest),
(self myRemove: (self smallest: self first)) selection.
]. " call selection on the list minus the smallest element"
!
" remove the first occurance of atom A from L "
myRemove: item
^self removeAt: (self find: item).
!
smallest: currentsmallest
" looks for the smallest element in the list
Currentsmallest is the current smallest "
self size = 0 ifTrue: [^currentsmallest.]
ifFalse: [
self first < currentsmallest ifTrue: [
^self allButFirst smallest: self first.]
ifFalse: [
^self allButFirst smallest: currentsmallest].
].
!
(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.
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 mergelists: m " assume L and M are sorted lists " self size = 0 ifTrue:[ ^m.] ifFalse: [ m size == 0 ifTrue: [ ^self.] ifFalse: [ self first < m first ifTrue: [ ^(OrderedCollection with: self first), (self allButFirst mergelists: m).] ifFalse: [ ^(OrderedCollection with: m first), (self mergelists: m allButFirst).] ] ] ! sub: start stop: stop counter: ctr " extract elements start to stop into a list" self size = 0 ifTrue: [ ^self.] ifFalse: [ ctr < start ifTrue: [ ^self allButFirst sub: start stop: stop counter: (ctr+1). ] ifFalse: [ ctr > stop ifTrue: [ ^#() asOrderedCollection. ] ifFalse: [ ^(OrderedCollection with: self first), (self allButFirst sub: start stop: stop counter: (ctr+1)). ] ] ] ! split " split the list in half:, ; returns ((first half)(second half)) " | length | length := self size. length = 0 ifTrue: [ ^(OrderedCollection with: self), (OrderedCollection with: self). ] ifFalse: [ length = 1 ifTrue: [ ^(OrderedCollection with: self), (OrderedCollection with: #() asOrderedCollection). ] ifFalse: [ ^(OrderedCollection with: (self sub: 1 stop: length/2 counter: 1)), (OrderedCollection with: (self sub: (length/2 + 1) stop: length counter: 1)). ] ] ! x = [6,3,4,9,10,1,7] print x, "\n" #print split(x) print mergesort(x), "\n"
; 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)))
)
)