МИНОБРНАУКИ РОССИИ Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования “Санкт-Петербургский государственный электротехнический университет “ЛЭТИ” им. В.И. Ульянова (Ленина)” (СПбГЭТУ) Факультет компьютерных технологий и информатики (ФКТИ) Кафедра МОЭВМ Отчёт по лабораторной работе №1 по дисциплине «Построение и анализ алгоритмов» Выполнил: студент группы 1303 Леонтьев Ю.А. Проверил: аспирант кафедры МОЭВМ Романенко Д.А. г. Санкт-Петербург 2013 г. ЗАДАНИЕ Вариант 10. Сортировка массивов слиянием (простое слияние). Необходимо генерировать исходные данные, одним из подходящих способов: Генерация: при случайной генерации задаются тип элементов, размер массива, диапазон значений элементов. Визуализация: Можно использовать любые простейшие графические средства, в крайнем случае, в этом задании можно использовать вывод в консоль Указания. Основной упор в задании делается на проведение экспериментального испытания (исследования) алгоритма (программной реализации). При этом оценивается эффективность алгоритма (его вариаций, разновидностей, модификаций). Основной показатель эффективности в этих заданиях - это время выполнения. Время выполнения должно измеряться, во-первых, с использованием компьютерного таймера. Во-вторых, требуется в ходе выполнения программы подсчитывать количество произведенных базовых операций алгоритма, например, операций сравнения и операций присваивания (перемещения элементов). Во всех случаях рекомендуется провести сравнения (по тем показателям, по которым это возможно) с каким-либо «эталонным» алгоритмом (реализацией), например, с системной функцией qsort или с какой-либо ещё библиотечной функцией. ОПИСАНИЕ АЛГОРИТМА Шаг 1. Исходный файл f разбивается на два вспомогательных файла f1 и f2. Шаг 2. Вспомогательные файлы f1 и f2 сливаются в файл f, при этом одиночные элементы образуют упорядоченные пары. Шаг 3. Полученный файл f вновь обрабатывается, как указано в шагах 1 и 2. При этом упорядоченные пары переходят в упорядоченные четверки. Шаг 4. Повторяя шаги, сливаем четверки в восьмерки и т.д., каждый раз удваивая длину слитых последовательностей до тех пор, пока не будет упорядочен целиком весь файл Признаками конца сортировки простым слиянием являются следующие условия: длина серии не меньше количества элементов в файле (определяется после фазы слияния); количество серий равно 1 (определяется на фазе слияния). при однофазной сортировке второй по счету вспомогательный файл после распределения серий остался пустым. ПРИМЕР РАБОТЫ АНАЛИЗ РЕЗУЛЬТАТОВ ПОЛУЧЕННЫХ С ПОМОЩЬЮ ПРОГРАММЫ В таблице 1 представлены результаты работы программы. Размер массива 10 20 30 40 50 60 70 80 90 100 Время выполнения (с) Количество итераций 0,00688288254823419 0,00705618498104741 0,00722978065023199 0,00749794490475324 0,0077339509538433 0,00786991467830376 0,00829178343192325 0,00830336625003838 0,00841929218731821 0,00829588873457396 115 266 395 607 758 906 1200 1368 1539 1709 Таблица 1 Время выполнения функции qsort(с) 0,00302570603525965 0,00318356470961589 0,0039562413803651 0,00368255451758159 0,00394646685163025 0,00389808291947702 0,00425631947291549 0,00420744682196528 0,00409601716819452 0,00505294375034282 График зависимости времени от размера массива указан на рисунке 2 Рис.2 0.009 Время выполнения(с) 0.008 0.007 0.006 0.005 0.004 0.003 0.002 0.001 0 10 20 30 40 50 60 70 80 90 100 Время выполнения(с) График зависимости количества итераций от количества элементов массива представлен на рисунке 3. Рис.3 Количество итераций 1800 1600 1400 1200 1000 Количество итераций 800 600 400 200 0 10 20 30 40 50 60 70 80 90 100 График зависимости времени выполнения программы и времени выполнения функции qsort() от количества элементов массива представлен на рисунке 4. Рис.4 0.009 0.008 0.007 0.006 Время Выполнения (с) 0.005 0.004 Время выполнения qsort 0.003 0.002 0.001 0 1 2 3 4 5 6 7 8 9 10 Количество итераций для сортировки слиянием можно найти по формуле O(log2(n)). В таблице 2 представлены фактические и теоретические значения количества итераций. Таблица 2 Размер массива 10 20 30 40 50 60 70 80 90 100 O(log2(n)) 33 86 147 213 282 354 429 506 584 664 Количество итераций 115 266 395 607 758 906 1200 1368 1539 1709 По данным можно сделать следующие выводы: 1. С увеличением количества элементов в массиве увеличивается время выполнения программы и количество итераций при сортировке слиянием (простое слияние). 2. Время выполнения библиотечной функции быстрой сортировки qsort намного быстрее. 3. Данная реализация алгоритма сортировки слиянием имеет спецификацию, которая не позволяет вычислить количество итераций. Поэтому значительно отличаются теоретические и практические значения количества итераций. ИСХОДНЫЙ КОД ПРОГРАММЫ Sort.cpp #include #include #include #include #include "StdAfx.h" "sort.h" <time.h> <stdio.h> <string.h> void Str(char *name) { fstream fout; fout.open(name); while (!fout.eof()) { getline(fout,str); } } void Simple_Merging_Sort (char *name){ int a1, a2, k, i, j, kol, tmp; int kol_ch=0; int *A; FILE *f, *f1, *f2; string str1=""; kol = 0; if ( (f = fopen(name,"r")) == NULL ) printf("\nИсходный файл не может быть прочитан..."); else { while ( !feof(f) ) { fscanf(f,"%d",&a1); kol++; kol_op++; } fclose(f); kol_ch=kol-1; A=new int[kol_ch]; int i1=0; FILE *ft; ft=fopen("1.txt","rt"); while ( !feof(f) ) { fscanf(ft,"%d",&A[i1]); i1++; } i1--; fclose(ft); str1 = "Исходный массив:\n"; Str(name); str1+=str; str=str1; } k = 1; while ( k < kol ){ f = fopen(name,"r"); f1 = fopen("smsort_1","w"); f2 = fopen("smsort_2","w"); if ( !feof(f) ) fscanf(f,"%d",&a1); while ( !feof(f) ){ for ( i = 0; i < k && !feof(f) ; i++ ){ kol_op++; fprintf(f1,"%d ",a1); fscanf(f,"%d",&a1); } for ( j = 0; j < k && !feof(f) ; j++ ){ kol_op++; fprintf(f2,"%d ",a1); fscanf(f,"%d",&a1); } kol_op++; } fclose(f2); fclose(f1); fclose(f); f = fopen(name,"w"); f1 = fopen("smsort_1","r"); f2 = fopen("smsort_2","r"); if ( !feof(f1) ) fscanf(f1,"%d",&a1); if ( !feof(f2) ) fscanf(f2,"%d",&a2); while ( !feof(f1) && !feof(f2) ){ kol_op++; i = 0; j = 0; while ( i < k && j < k && !feof(f1) && !feof(f2) ) { if ( a1 < a2 ) { kol_op++; fprintf(f,"%d ",a1); fscanf(f1,"%d",&a1); i++; } else { kol_op++; fprintf(f,"%d ",a2); fscanf(f2,"%d",&a2); j++; } } while ( i < k && !feof(f1) ) { kol_op++; fprintf(f,"%d ",a1); fscanf(f1,"%d",&a1); i++; } while ( j < k && !feof(f2) ) { kol_op++; fprintf(f,"%d ",a2); fscanf(f2,"%d",&a2); j++; } } while ( !feof(f1) ) { kol_op++; fprintf(f,"%d ",a1); fscanf(f1,"%d",&a1); } while ( !feof(f2) ) { kol_op++; fprintf(f,"%d ",a2); fscanf(f2,"%d",&a2); } fclose(f2); fclose(f1); fclose(f); k *= 2; kol_op++; str += "\n_______________________________\nf1 массив:\n"; str1=str; Str("smsort_1"); str1+=str; str=str1; str += "\n_______________________________\nf2 массив:\n"; str1=str; Str("smsort_2"); str1+=str; str=str1; str += "\n_______________________________\nслияние:\n"; str1=str; Str("1.txt"); str1+=str; str=str1; } remove("smsort_1"); remove("smsort_2"); sortq(kol_ch, A); } int compare(const void* first, const void* second) { return *((int*)first) - *((int*)second); } string to_string(int val) { char buff[32]; sprintf(buff,"%d",val); return string(buff); } void sortq(int kol_ch, int* A) { double t1 = omp_get_wtime(); // системное время до выполнения функции string str1=""; str1="\n_______________________\nQsort:\n"; qsort(A, kol_ch, sizeof(int), compare); for (int i=0;i<kol_ch;i++) { str1+=to_string(A[i]); str1+=" "; } str+=str1; double t2 = omp_get_wtime(); // время после выполнения функции time1 = t2 - t1; time1=time1; } Rand.cpp #include #include #include #include #include "stdafx.h" <string> <iostream> <fstream> "Form1.h" using namespace std; void random(int kol, int range, int min) { FILE *f; f = fopen("1.txt","w"); srand(time(0)); // int kol = 10; // int range =99; // Разница между минимумом и максимумом // int min = -100;// Левая граница нужного промежутка. for (int i=0; i<kol;i++) fprintf(f,"%d ",(rand() % (range+1) + min)); //int x = rand() % (range+1) + min; //return x; fclose(f); } int random_1(int kol, int range, int min) { if (kol>(range+1)) { return 1; // получается то, что наш массив длинее интервала, и все разные числа быть не могут. } srand(time(0)); FILE *f; int *parr; parr = new int[kol]; int i, j; int dup_flag; int rand_val, range_width= range+1; for ( i= 0; i<kol; i++ ) { for ( ; ; ) { rand_val= rand() % (range+1) + min; dup_flag= 0; for ( j= 0; j<i; j++ ) { if ( rand_val == parr[j] ) { dup_flag= 1; break; } } if ( !dup_flag ) { break; } } parr[i]= rand_val; } f = fopen("1.txt","w"); for (int k=0; k<i;k++) fprintf(f,"%d ", parr[k]); fclose(f); } Form1.h private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { string str=""; Print(str); double t1 = omp_get_wtime(); // системное время до выполнения Simple_Merging_Sort("1.txt"); double t2 = omp_get_wtime(); // время после выполнения double time = t2 - t1; richTextBox1->Text +="\n_______________________\nВремя выполнения:\n" + time; richTextBox1->Text +="\n_____________________________\nКоличество базовых операций:\n" + kol_op; richTextBox1->Text +="\n_____________________________\nВремя выполнения Qsort:\n" + Time_Qsort(); Вывод При выполнении лабораторной работы были получены практические навыки работы с различными сортировками. Была составлена программа с использованием сортировки слиянием (простое слияние). Ошибок в её работе не обнаружено.