Skip to content

Commit dce5b7a

Browse files
committed
Implemented merge sort in List::sort
Goodbye bubble sort
1 parent b957bfe commit dce5b7a

1 file changed

Lines changed: 76 additions & 17 deletions

File tree

src/charly/stdlib/boot.ch

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -556,9 +556,7 @@ class Timer {
556556
}
557557

558558
func sort(compare_function = null) {
559-
let length = @length
560-
let i = 0
561-
let had_swaps = true
559+
const length = @length
562560

563561
if length <= 1 {
564562
return self
@@ -568,24 +566,85 @@ class Timer {
568566
compare_function = ->(left, right) left <=> right
569567
}
570568

571-
while (had_swaps) {
572-
i = 0
573-
had_swaps = false
569+
// secondary buffer, same size
570+
let buffer = self.sublist(0, length)
574571

575-
if @length != length {
576-
throw "List size changed during sort"
577-
}
572+
// we alternate between these on each pass
573+
let src = self
574+
let dst = buffer
575+
576+
let width = 1
577+
while (width < length) {
578+
let i = 0
579+
580+
while (i < length) {
581+
let left = i
582+
let mid = i + width
583+
let right = i + width * 2
584+
585+
if mid > length {
586+
mid = length
587+
}
588+
if right > length {
589+
right = length
590+
}
591+
592+
// if there's no right run, just copy the tail
593+
if mid >= right {
594+
let t = left
595+
while (t < right) {
596+
dst[t] = src[t]
597+
t += 1
598+
}
599+
i = right
600+
continue
601+
}
578602

579-
@each(->(value, index) {
580-
if index < length - 1 {
581-
const next_value = self[index + 1]
582-
if compare_function(value, next_value) > 0 {
583-
self[index] = next_value
584-
self[index + 1] = value
585-
had_swaps = true
603+
let a = left
604+
let b = mid
605+
let k = left
606+
607+
while (a < mid && b < right) {
608+
if compare_function(src[a], src[b]) <= 0 {
609+
dst[k] = src[a]
610+
a += 1
611+
} else {
612+
dst[k] = src[b]
613+
b += 1
586614
}
615+
k += 1
616+
}
617+
618+
while (a < mid) {
619+
dst[k] = src[a]
620+
a += 1
621+
k += 1
587622
}
588-
})
623+
624+
while (b < right) {
625+
dst[k] = src[b]
626+
b += 1
627+
k += 1
628+
}
629+
630+
i = right
631+
}
632+
633+
// next pass: swap roles
634+
let tmp = src
635+
src = dst
636+
dst = tmp
637+
638+
width = width * 2
639+
}
640+
641+
// if final result ended up in buffer, copy back once
642+
if src != self {
643+
let i = 0
644+
while (i < length) {
645+
self[i] = src[i]
646+
i += 1
647+
}
589648
}
590649

591650
self

0 commit comments

Comments
 (0)