123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- package sort
- import "core:mem"
- bubble_sort_proc :: 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-1 {
- 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-1 {
- 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 :: 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_proc(a[0:i], f);
- quick_sort_proc(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 :: 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-1 {
- 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 {
- for j in 0..a-1 {
- 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-1 {
- 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 {
- for j in 0..a-1 {
- 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 mem.compare_byte_ptrs(&a[0], &b[0], min(len(a), len(b)));
- }
|