mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-01 19:02:13 +00:00
214 lines
3.7 KiB
Odin
214 lines
3.7 KiB
Odin
bubble_sort :: proc(array: $A/[]$T, f: proc(T, T) -> int) {
|
|
assert(f != nil);
|
|
count := len(array);
|
|
|
|
init_j, last_j := 0, count-1;
|
|
|
|
for {
|
|
init_swap, prev_swap := -1, -1;
|
|
|
|
for j in init_j..last_j {
|
|
if f(array[j], array[j+1]) > 0 {
|
|
array[j], array[j+1] = array[j+1], array[j];
|
|
prev_swap = j;
|
|
if init_swap == -1 do init_swap = j;
|
|
}
|
|
}
|
|
|
|
if prev_swap == -1 do return;
|
|
|
|
init_j = max(init_swap-1, 0);
|
|
last_j = prev_swap;
|
|
}
|
|
}
|
|
|
|
bubble_sort :: proc(array: $A/[]$T) {
|
|
count := len(array);
|
|
|
|
init_j, last_j := 0, count-1;
|
|
|
|
for {
|
|
init_swap, prev_swap := -1, -1;
|
|
|
|
for j in init_j..last_j {
|
|
if array[j] > array[j+1] {
|
|
array[j], array[j+1] = array[j+1], array[j];
|
|
prev_swap = j;
|
|
if init_swap == -1 do init_swap = j;
|
|
}
|
|
}
|
|
|
|
if prev_swap == -1 do return;
|
|
|
|
init_j = max(init_swap-1, 0);
|
|
last_j = prev_swap;
|
|
}
|
|
}
|
|
|
|
quick_sort :: proc(array: $A/[]$T, f: proc(T, T) -> int) {
|
|
assert(f != nil);
|
|
a := array;
|
|
n := len(a);
|
|
if n < 2 do return;
|
|
|
|
p := a[n/2];
|
|
i, j := 0, n-1;
|
|
|
|
loop: for {
|
|
for f(a[i], p) < 0 do i += 1;
|
|
for f(p, a[j]) < 0 do j -= 1;
|
|
|
|
if i >= j do break loop;
|
|
|
|
a[i], a[j] = a[j], a[i];
|
|
i += 1;
|
|
j -= 1;
|
|
}
|
|
|
|
quick_sort(a[0..i], f);
|
|
quick_sort(a[i..n], f);
|
|
}
|
|
|
|
quick_sort :: proc(array: $A/[]$T) {
|
|
a := array;
|
|
n := len(a);
|
|
if n < 2 do return;
|
|
|
|
p := a[n/2];
|
|
i, j := 0, n-1;
|
|
|
|
loop: for {
|
|
for a[i] < p do i += 1;
|
|
for p < a[j] do j -= 1;
|
|
|
|
if i >= j do break loop;
|
|
|
|
a[i], a[j] = a[j], a[i];
|
|
i += 1;
|
|
j -= 1;
|
|
}
|
|
|
|
quick_sort(a[0..i]);
|
|
quick_sort(a[i..n]);
|
|
}
|
|
|
|
_log2 :: proc(n: int) -> int {
|
|
res := 0;
|
|
for ; n != 0; n >>= 1 do res += 1;
|
|
return res;
|
|
}
|
|
|
|
merge_sort :: proc(array: $A/[]$T, f: proc(T, T) -> int) {
|
|
merge_slices :: proc(arr1, arr2, out: A, f: proc(T, T) -> int) {
|
|
N1, N2 := len(arr1), len(arr2);
|
|
i, j := 0, 0;
|
|
for k in 0..N1+N2 {
|
|
if j == N2 || i < N1 && j < N2 && f(arr1[i], arr2[j]) < 0 {
|
|
out[k] = arr1[i];
|
|
i += 1;
|
|
} else {
|
|
out[k] = arr2[j];
|
|
j += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
assert(f != nil);
|
|
|
|
arr1 := array;
|
|
N := len(arr1);
|
|
arr2 := make([]T, N);
|
|
defer free(arr2);
|
|
|
|
a, b, m, M := N/2, N, 1, _log2(N);
|
|
|
|
for i in 0..M+1 {
|
|
for j in 0..a {
|
|
k := 2*j*m;
|
|
merge_slices(arr1[k..k+m], arr1[k+m..k+m+m], arr2[k..], f);
|
|
}
|
|
if N-b > m {
|
|
k := 2*a*m;
|
|
merge_slices(arr1[k..k+m], arr1[k+m..k+m+(N-b)&(m-1)], arr2[k..], f);
|
|
} else {
|
|
copy(arr2[b..N], arr1[b..N]);
|
|
}
|
|
arr1, arr2 = arr2, arr1;
|
|
m <<= 1;
|
|
a >>= 1;
|
|
b = a << uint(i) << 2;
|
|
}
|
|
|
|
if M & 1 == 0 do copy(arr2, arr1);
|
|
}
|
|
|
|
merge_sort :: proc(array: $A/[]$T) {
|
|
merge_slices :: proc(arr1, arr2, out: A) {
|
|
N1, N2 := len(arr1), len(arr2);
|
|
i, j := 0, 0;
|
|
for k in 0..N1+N2 {
|
|
if j == N2 || i < N1 && j < N2 && arr1[i] < arr2[j] {
|
|
out[k] = arr1[i];
|
|
i += 1;
|
|
} else {
|
|
out[k] = arr2[j];
|
|
j += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
arr1 := array;
|
|
N := len(arr1);
|
|
arr2 := make([]T, N);
|
|
defer free(arr2);
|
|
|
|
a, b, m, M := N/2, N, 1, _log2(N);
|
|
|
|
for i in 0..M+1 {
|
|
for j in 0..a {
|
|
k := 2*j*m;
|
|
merge_slices(arr1[k..k+m], arr1[k+m..k+m+m], arr2[k..]);
|
|
}
|
|
if N-b > m {
|
|
k := 2*a*m;
|
|
merge_slices(arr1[k..k+m], arr1[k+m..k+m+(N-b)&(m-1)], arr2[k..]);
|
|
} else {
|
|
copy(arr2[b..N], arr1[b..N]);
|
|
}
|
|
arr1, arr2 = arr2, arr1;
|
|
m <<= 1;
|
|
a >>= 1;
|
|
b = a << uint(i) << 2;
|
|
}
|
|
|
|
if M & 1 == 0 do copy(arr2, arr1);
|
|
}
|
|
|
|
|
|
|
|
compare_ints :: proc(a, b: int) -> int {
|
|
switch delta := a - b; {
|
|
case delta < 0: return -1;
|
|
case delta > 0: return +1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
compare_f32s :: proc(a, b: f32) -> int {
|
|
switch delta := a - b; {
|
|
case delta < 0: return -1;
|
|
case delta > 0: return +1;
|
|
}
|
|
return 0;
|
|
}
|
|
compare_f64s :: proc(a, b: f64) -> int {
|
|
switch delta := a - b; {
|
|
case delta < 0: return -1;
|
|
case delta > 0: return +1;
|
|
}
|
|
return 0;
|
|
}
|
|
compare_strings :: proc(a, b: string) -> int {
|
|
return __string_cmp(a, b);
|
|
}
|