/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* sort.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: cacharle +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/01/19 09:12:02 by cacharle #+# #+# */ /* Updated: 2021/09/10 19:35:34 by charles ### ########.fr */ /* */ /* ************************************************************************** */ #include "push_swap.h" static int frame_length(t_stack *st, int frame_index) { return (stack_length(st) - frame_index); } static void push_swap_sort3(t_stack *main) { int a, b, c; a = main->elements[main->top]; b = main->elements[main->top - 1]; c = main->elements[main->top - 2]; /* 2 3 1 rra */ if (a < b && b > c && a > c) stack_reverse_rotate_print(main); /* 3 1 2 ra */ else if (a > b && b < c && a > c) stack_rotate_print(main); /* 3 2 1 ra sa */ else if (a > b && b > c && a > c) { stack_rotate_print(main); stack_swap_print(main); } /* 2 1 3 sa */ else if (a > b && b < c && a < c) stack_swap_print(main); /* 1 3 2 sa ra*/ else if (a < b && b > c && a < c) { stack_swap_print(main); stack_rotate_print(main); } } static int stack_cmp(t_stack *stack, int x, int y) { if (stack->tag == STACK_A) return (x < y); else return (x > y); } /* ** main : stack to sort ** tmp : temporary stack used to store pivot > values ** main_frame : main current sorting frame index ** (ignore values beyond a certain index, ** which bellong to previous recursions) ** ** store pivot value ** hide it at the bottom of the stack ** iterate over the current frame ** if < pivot, push it to tmp stack ** else, hide it with the pivot ** put all hidden elements on the top of the stack ** these form the new frame ** ** we have splitted the elements of the frame in upper and lower partition ** each of those will be sorted in the next recursion */ static void push_swap_qsort_partition(t_stack *main, t_stack *tmp, int main_frame) { int pivot; int hidden_count; int frame_len; pivot = stack_peek(main); stack_rotate_print(main); hidden_count = 1; frame_len = frame_length(main, main_frame) - 1; while (frame_len > 0) { if (stack_cmp(main, stack_peek(main) , pivot)) stack_push_to_print(main, tmp); else { stack_rotate_print(main); hidden_count++; } frame_len--; } if (stack_peek(main) == pivot) return ; while (hidden_count-- > 0) stack_reverse_rotate_print(main); } static bool stack_frame_sorted(t_stack *stack, int frame_len) { int i; i = 0; while (i < frame_len - 1) { if (stack_cmp(stack, stack->elements[stack->top - 1 - i], stack->elements[stack->top - i])) return false; i++; } return true; } /* ** main : final stack where all sorted values will be stored ** tmp : temporary stack use to during partitionning ** main_frame : main stack sorting frame ** tmp_frame : tmp stack sorting frame ** ** base condition : the current main frame contain 0 or 1 element ** sort current partition and get new main frame ** according to the new frame: ** sort the new partition ** sort the tmp stack ** push all elements of tmp on main */ static void push_swap_qsort_rec(t_stack *main, t_stack *tmp, int main_frame, int tmp_frame) { int tmp_frame_len; /* printf("f: %d\n", main_frame); */ if (frame_length(main, main_frame) < 2) return ; if (stack_frame_sorted(main, frame_length(main, main_frame))) return ; if (main->tag == STACK_A && stack_length(main) == 3) return push_swap_sort3(main); if (frame_length(main, main_frame) == 2) { if (stack_cmp(main, main->elements[main->top - 1], main->elements[main->top])) stack_swap_print(main); return ; } push_swap_qsort_partition(main, tmp, main_frame); push_swap_qsort_rec(tmp, main, tmp_frame, stack_length(main)); stack_push_to_print(main, tmp); push_swap_qsort_rec(main, tmp, main_frame, stack_length(tmp)); stack_push_to_print(tmp, main); tmp_frame_len = frame_length(tmp, tmp_frame); while (tmp_frame_len-- > 0) stack_push_to_print(tmp, main); } /* ** wrapper for push_swap_qsort_rec */ void push_swap_qsort(t_stack *a, t_stack *b) { push_swap_qsort_rec(a, b, 0, 0); }