diff --git a/sort b/sort new file mode 100755 index 0000000..91ec744 Binary files /dev/null and b/sort differ diff --git a/sort.c b/sort.c new file mode 100644 index 0000000..63f14da --- /dev/null +++ b/sort.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include +#include + +#include "macro.h" + +typedef void (*sorter_t)(int *arr, size_t sz); + +typedef struct { + const char *name; + sorter_t func; +} sort_info_t; + +/* + * Написать сортировку вставками (не подглядывая в инторнеты!) + * arr -- целочисленный массив + * sz -- размер массива + */ +void insert_sort(int *arr, size_t sz) +{ + int i, j; + for(i = 1; i < sz; i++) + { + int k = arr[i]; + j = i - 1; + while(j >= 0 && arr[j] > k) + { + arr[j + 1] = arr[j]; + j--; + } + arr[j + 1] = k; + } +} + +void +bubble_sort(int *arr, size_t sz) +{ + int i, j; + int tmp; + + for (i = 0; i < sz; i++) { + for (j = i + 1; j < sz; j++) { + if (arr[i] > arr[j]) { + tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + } + } +} + +/* + Функция для слияния двух отсортированных + массивов в один. + + a -- указывает на первый элемент первого массива + b -- указывает на первый элемент второго массива + end -- указывает на первый элемент за границами второго массива + Результат записывается во временный массив tmp. + Первый элемент в tmp[0], второй в tmp[1] и т.д. + + Пример + массивы a = [1, 4, 5] + b = [2, 3, 6] + + a b end + | | | + \/ \/ \/ + | 1 | 4 | 5 | 2 | 3 | 6 | + + после вызова _merge в tmp должен получиться массив + | 1 | 2 | 3 | 4 | 5 | 6 | + + */ +static void +_merge(int *tmp, int *a, int *b, int *end) +{ + int tmp1 = 0, a1 = 0, b1 = 0; + int size_1 = b - a, size_2 = end - b; + while(a1 < size_1 && b1 < size_2) + { + if(a[a1] < b[b1]) + { + tmp[tmp1++] = a[a1++]; + } + else + { + tmp[tmp1++] = b[b1++]; + } + } + while(a1 < size_1) + { + tmp[tmp1] = a[a1]; + tmp1++; a1++; + } + while(b1 < size_2) + { + tmp[tmp1] = b[b1]; + tmp1++; b1++; + } + +} + +static void +_merge_sort_int(int *tmp, int *arr, size_t n) +{ + int half = n / 2; //индекс, который делит массивы пополам + + if (half > 1) + _merge_sort_int(tmp, arr, half); + if (n - half > 1) + _merge_sort_int(tmp + half, arr + half, n - half); + + // "слить" два отсортированных массива в один + //tmp - where new sorted array + _merge(tmp, arr, arr + half, arr + n); + // Скопировать данные из временного хранилища в + // оригинальный массив + memcpy(arr, tmp, n * sizeof(*tmp)); +} + +void +merge_sort(int *arr, size_t sz) +{ + int *tmp; + + if (sz < 2) + return; + tmp = malloc(sizeof(*arr) * sz); + assert(tmp); + _merge_sort_int(tmp, arr, sz); + free(tmp); +} + +void +print_arr(int *arr, size_t n) +{ + printf("{"); + for (int i = 0; i < n; i++) { + printf("%d, ", arr[i]); + } + printf("}\n"); +} + +#define _S(item) {#item, item} + +bool +test_all() +{ + #include "test_arrays.h" + TEST_ARR_INIT(testcases); + + sort_info_t sorters[] = { + _S(insert_sort), + //_S(bubble_sort), + _S(merge_sort), + }; + + int *temparr = NULL; + int temparr_len = 0; + + int allok = 1; + + for (int j = 0; j < ARRSZ(sorters); j++) { + sort_info_t cursort = sorters[j]; + printf("[+] %s\n", cursort.name); + + for (int i = 0; i < ARRSZ(testcases); i++) { + int len = testcases[i].len; + + printf("[+] testing %s\n", testcases[i].name); + if (len > temparr_len) { + // TODO: EER???? + temparr_len = len; + temparr = realloc(temparr, temparr_len * sizeof(*temparr)); + assert(temparr); + } + memcpy(temparr, testcases[i].unsorted, sizeof(*temparr) * len); + cursort.func(temparr, len); + int res = memcmp(temparr, testcases[i].sorted, sizeof(*temparr) * len); + if (res != 0) { + allok = 0; + printf("[-] arrays does not match \n"); + printf("your\n"); + print_arr(temparr, len); + printf("original\n"); + print_arr(testcases[i].sorted, len); + break; + } + } + } + if (allok) { + printf("[+] All OK!\n"); + } + if (temparr) + free(temparr); + return allok == 1; +} + +int +main(int argc, const char *argv[]) +{ + test_all(); + return 0; +}