Add slice.stable_sort* procedures

This commit is contained in:
gingerBill
2022-01-31 15:55:52 +00:00
parent 1a9ec776cb
commit 14a17fb36f
3 changed files with 61 additions and 12 deletions
+26
View File
@@ -56,6 +56,32 @@ sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
} }
} }
// stable_sort sorts a slice
stable_sort :: proc(data: $T/[]$E) where ORD(E) {
when size_of(E) != 0 {
if n := len(data); n > 1 {
_stable_sort_general(data, struct{}{}, .Ordered)
}
}
}
// stable_sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j"
stable_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
when size_of(E) != 0 {
if n := len(data); n > 1 {
_stable_sort_general(data, less, .Less)
}
}
}
stable_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
when size_of(E) != 0 {
if n := len(data); n > 1 {
_stable_sort_general(data, cmp, .Cmp)
}
}
}
is_sorted :: proc(array: $T/[]$E) -> bool where ORD(E) { is_sorted :: proc(array: $T/[]$E) -> bool where ORD(E) {
for i := len(array)-1; i > 0; i -= 1 { for i := len(array)-1; i > 0; i -= 1 {
if array[i] < array[i-1] { if array[i] < array[i-1] {
+23
View File
@@ -175,3 +175,26 @@ _quick_sort_general :: proc(data: $T/[]$E, a, b, max_depth: int, call: $P, $KIND
insertion_sort(data, a, b, call) insertion_sort(data, a, b, call)
} }
} }
// merge sort
_stable_sort_general :: proc(data: $T/[]$E, call: $P, $KIND: Sort_Kind) where (ORD(E) && KIND == .Ordered) || (KIND != .Ordered) #no_bounds_check {
less :: #force_inline proc(a, b: $E, call: $P) -> bool {
when KIND == .Ordered {
return a < b
} else when KIND == .Less {
return call(a, b)
} else when KIND == .Cmp {
return call(a, b) == .Less
} else {
#panic("unhandled Sort_Kind")
}
}
n := len(data)
for i in 1..<n {
for j := i; j > 0 && less(data[j], data[j-1], call); j -= 1 {
swap(data, j, j-1)
}
}
}