Загрузка данных
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int FillInc(int n, int arr[]){
for (int i = 0; i < n; i++) arr[i] = i+1;
return 0;
}
int FillDec(int n, int arr[]){
for (int i = 0; i < n; i++) arr[i] = n-i;
return 0;
}
int FillRand(int n, int arr[]){
for (int i = 0; i < n; i++) arr[i] = rand() % 1000;
return 0;
}
int CheckSum(int n, int arr[]){
int sum = 0;
for (int i = 0; i < n; i++) sum += arr[i];
return sum;
}
int RunNumber(int n, int arr[]){
int series = 1;
for (int i = 0; i < n-1; i++) if(arr[i+1] < arr[i]) series++;
return series;
}
void PrintMas(int n, int arr[]){
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
printf("\n");
}
void CopyArray(int n, int src[], int dest[]){
for (int i = 0; i < n; i++) dest[i] = src[i];
}
// Глобальные счетчики
unsigned long long Mf = 0, Cf = 0;
int max_depth = 0, current_depth = 0;
void reset_counters() {
Mf = 0;
Cf = 0;
max_depth = 0;
current_depth = 0;
}
// Первая версия QuickSort (рекурсивная, два вызова)
void QuickSortV1(int arr[], int L, int R) {
if (L >= R) return;
current_depth++;
if (current_depth > max_depth) max_depth = current_depth;
int x = arr[L];
int i = L, j = R;
do {
while (arr[i] < x) { Cf++; i++; }
while (arr[j] > x) { Cf++; j--; }
if (i <= j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
Mf += 3;
i++;
j--;
}
} while (i <= j);
QuickSortV1(arr, L, j);
QuickSortV1(arr, i, R);
current_depth--;
}
// Вторая версия QuickSort (рекурсия только для меньшей части)
void QuickSortV2(int arr[], int L, int R) {
while (L < R) {
current_depth++;
if (current_depth > max_depth) max_depth = current_depth;
int x = arr[L];
int i = L, j = R;
do {
while (arr[i] < x) { Cf++; i++; }
while (arr[j] > x) { Cf++; j--; }
if (i <= j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
Mf += 3;
i++;
j--;
}
} while (i <= j);
if (j - L > R - i) {
QuickSortV2(arr, i, R);
R = j;
} else {
QuickSortV2(arr, L, j);
L = i;
}
current_depth--;
}
}
int main() {
srand(time(NULL));
// ЗАДАНИЕ 2. Проверка правильности QuickSortV1
printf("ЗАДАНИЕ 2. Проверка правильности QuickSort\n");
printf("============================================\n");
int test_n = 10;
int test_arr[10];
FillRand(test_n, test_arr);
printf("Исходный массив: ");
PrintMas(test_n, test_arr);
printf("Контрольная сумма: %d\n", CheckSum(test_n, test_arr));
printf("Число серий: %d\n", RunNumber(test_n, test_arr));
int test_copy[10];
CopyArray(test_n, test_arr, test_copy);
reset_counters();
QuickSortV1(test_copy, 0, test_n-1);
printf("\nПосле сортировки: ");
PrintMas(test_n, test_copy);
printf("Контрольная сумма: %d\n", CheckSum(test_n, test_copy));
printf("Число серий: %d\n", RunNumber(test_n, test_copy));
printf("C = %llu, M = %llu, Мф+Сф = %llu\n\n", Cf, Mf, Cf+Mf);
// ЗАДАНИЕ 3. Таблица трудоемкости
printf("ЗАДАНИЕ 3. Трудоемкость метода Хоара QuickSort\n");
printf("================================================\n");
printf(" N | Убывающий | Возрастающий | Случайный\n");
printf("---------------------------------------------------\n");
int n_values[] = {100, 200, 300, 400, 500};
int num_sizes = 5;
for (int i = 0; i < num_sizes; i++) {
int n = n_values[i];
int arr_inc[n], arr_dec[n], arr_rand[n];
int arr_copy[n];
// Убывающий массив
FillDec(n, arr_dec);
CopyArray(n, arr_dec, arr_copy);
reset_counters();
QuickSortV1(arr_copy, 0, n-1);
int dec_sum = Cf + Mf;
// Возрастающий массив
FillInc(n, arr_inc);
CopyArray(n, arr_inc, arr_copy);
reset_counters();
QuickSortV1(arr_copy, 0, n-1);
int inc_sum = Cf + Mf;
// Случайный массив
FillRand(n, arr_rand);
CopyArray(n, arr_rand, arr_copy);
reset_counters();
QuickSortV1(arr_copy, 0, n-1);
int rand_sum = Cf + Mf;
printf(" %3d | %5d | %5d | %5d\n",
n, dec_sum, inc_sum, rand_sum);
}
printf("===================================================\n");
printf("\nВЫВОД: Метод Хоара QuickSort ");
printf("СИЛЬНО ЗАВИСИТ от исходной упорядоченности.\n");
printf("На упорядоченных массивах (возр. и убыв.) трудоемкость O(n²),\n");
printf("на случайных массивах O(n log n).\n\n");
// ЗАДАНИЕ 4. Глубина рекурсии
printf("ЗАДАНИЕ 4. Глубина рекурсии QuickSort\n");
printf("=============================================================\n");
printf(" N | QuickSortV1 | QuickSortV2 |\n");
printf(" | Убыв. Возр. Случ. | Убыв. Возр. Случ. |\n");
printf("-------------------------------------------------------------\n");
for (int i = 0; i < num_sizes; i++) {
int n = n_values[i];
int arr_inc[n], arr_dec[n], arr_rand[n];
int arr_copy[n];
// QuickSortV1
// Убывающий
FillDec(n, arr_dec);
CopyArray(n, arr_dec, arr_copy);
reset_counters();
QuickSortV1(arr_copy, 0, n-1);
int dec_depth1 = max_depth;
// Возрастающий
FillInc(n, arr_inc);
CopyArray(n, arr_inc, arr_copy);
reset_counters();
QuickSortV1(arr_copy, 0, n-1);
int inc_depth1 = max_depth;
// Случайный
FillRand(n, arr_rand);
CopyArray(n, arr_rand, arr_copy);
reset_counters();
QuickSortV1(arr_copy, 0, n-1);
int rand_depth1 = max_depth;
// QuickSortV2
// Убывающий
FillDec(n, arr_dec);
CopyArray(n, arr_dec, arr_copy);
reset_counters();
QuickSortV2(arr_copy, 0, n-1);
int dec_depth2 = max_depth;
// Возрастающий
FillInc(n, arr_inc);
CopyArray(n, arr_inc, arr_copy);
reset_counters();
QuickSortV2(arr_copy, 0, n-1);
int inc_depth2 = max_depth;
// Случайный
FillRand(n, arr_rand);
CopyArray(n, arr_rand, arr_copy);
reset_counters();
QuickSortV2(arr_copy, 0, n-1);
int rand_depth2 = max_depth;
printf(" %3d | %3d %3d %3d | %3d %3d %3d |\n",
n, dec_depth1, inc_depth1, rand_depth1,
dec_depth2, inc_depth2, rand_depth2);
}
printf("=============================================================\n");
printf("\nВЫВОД: Вторая версия значительно уменьшает глубину рекурсии,\n");
printf("особенно на упорядоченных массивах (с O(n) до O(log n)).\n");
return 0;
}