mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
Add slice.stable_sort* procedures
This commit is contained in:
+12
-12
@@ -305,21 +305,21 @@ filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -
|
|||||||
}
|
}
|
||||||
|
|
||||||
scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U)->V, allocator := context.allocator) -> []V {
|
scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U)->V, allocator := context.allocator) -> []V {
|
||||||
if len(s) == 0 { return {} }
|
if len(s) == 0 { return {} }
|
||||||
|
|
||||||
res := make([]V, len(s), allocator)
|
res := make([]V, len(s), allocator)
|
||||||
p := as_ptr(s)
|
p := as_ptr(s)
|
||||||
q := as_ptr(res)
|
q := as_ptr(res)
|
||||||
r := initializer
|
r := initializer
|
||||||
|
|
||||||
for l := len(s); l > 0; l -= 1 {
|
for l := len(s); l > 0; l -= 1 {
|
||||||
r = f(r, p[0])
|
r = f(r, p[0])
|
||||||
q[0] = r
|
q[0] = r
|
||||||
p = p[1:]
|
p = p[1:]
|
||||||
q = q[1:]
|
q = q[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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] {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user