Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

СиАОД_1-4.docx

.pdf
Скачиваний:
5
Добавлен:
23.01.2025
Размер:
1.33 Mб
Скачать

Федеральное агентство связи Ордена Трудового Красного Знамени

Федеральное государственное бюджетное образовательное учреждение высшего образования

«Московский технический университет связи и информатики»

Кафедра Математической Кибернетики и Информационных Технологий

Отчет по курсовй работе

по предмету «СиАОД»

на темы:

«Методы сортировки» , «Методы поиска», ​ «Рекурсия», «Алгоритмы поиска подстроки» ​

Выполнил: студент группы БВТ225

Руководитель:

Кутейников

Москва 2024

1

Задание 1 Методы сортировки​

3

Цель работы​

3

Ход работы​

3

замеры времени для матрицы double​

6

Замеры времени 32 битные целое​

7

Код программы (частично)​

8

Вывод​

12

Задание 2 Методы поиска​

13

Ход работы​

13

Замеры времени​

29

Выводы​

30

задание 3 Рекурсия​

31

Выполнение​

31

Замеры времени​

38

Вывод​

41

задание 4 Поиск подстроки в строке​

42

Цель работы​

42

Ход работы​

42

libstdc++ find algorithm​

47

The Knute Morris Pratt search method find :​

48

Замеры времени​

49

Выводы​

49

Список Литературы​

50

2

Задание 1 Методы сортировки

Цель работы

Реализовать заданный метод сортировки числовой матрицы в соответствии с индивидуальным заданием. Для всех вариантов добавить реализацию быстрой сортировки (quicksort). Оценить время работы каждого алгоритма сортировки и сравнить его со временем стандартной функции сортировки, используемой в выбранном языке программирования.

Вариант 18

Пирамидальная сортировка.

Ход работы

В соответствии с заданием, реализовали алгоритмы быстрой сортировки:

template <typename RandomIt, typename Cmp >

inline RandomIt partition(RandomIt first, RandomIt last, Cmp &cmp) { auto pivot = std::prev(last, 1);

auto i = first;

for (auto j = first; j != pivot; ++j) { // bool format

if (cmp(*j, *pivot)) { std::iter_swap(i++, j);

}

}

std::iter_swap(i, pivot); return i;

}

template <typename RandomIt, typename Cmp>

inline void quickSort(RandomIt first, RandomIt last, Cmp cmp ) { if (std::distance(first, last) < 2) {

return;

}

auto p = edu::partition(first, last, cmp); quickSort(first, p, cmp);

quickSort(p + 1, last, cmp);

}

3

Также реализовали алгоритм пирамидальной сортировки: ​

template <class RandomIt, class Compare>

inline void heapify(RandomIt first, RandomIt last, RandomIt i, Compare cmp) {

auto size = std::distance(first, last);

auto double_dist = 2 * std::distance(first, i); auto largest = i;

auto l = first + double_dist + 1; auto r = first + double_dist + 2;

if (l < last && !cmp(*l, *largest)) largest = l;

if (r < last && !cmp(*r, *largest)) largest = r;

if (largest != i) { std::iter_swap(i, largest);

heapify(first, last, first + std::distance(first, largest), cmp);

}

}

template <class RandomIt, class Compare>

inline void heap_sort(RandomIt first, RandomIt last, Compare cmp ) { auto size = std::distance(first, last);

for (auto i = size / 2 - 1; i >= 0; --i) heapify(first, last, first + i, cmp);

for (auto i = size - 1; i > 0; --i) { std::iter_swap(first, first + i); heapify(first, first + i, first, cmp);

}

}

Также, реализовали алгоритм сортировки Шелла:

template <typename RandomAccessIterator_, typename Compare_> inline void shell_sort(RandomAccessIterator_ first, RandomAccessIterator_ last,

Compare_ comp) {

4

for (std::size_t interval = std::distance(first, last) / 2; interval > 0;

interval /= 2) {

for (RandomAccessIterator_ it = first + interval; it < last; ++it)

{

auto temp = *it; RandomAccessIterator_ jt = it;

for (; jt >= interval + first && comp(temp, *(jt - interval)); jt -= interval) {

*jt = *(jt - interval);

}

*jt = temp;

}

}

}

Реализовали еще несколько алгоритмов в похожем стиле.

Компиляцию производим при помощи утилиты CMake, в которо для сборки типа release установили опции оптимизации -02:

Запускаем программу следующей командой : ​

time ./test_sort --width=10000 --height=5000 -r --rndMin=0 --rndMax=10000

Сравнение времени выполнения алгоритмов, для массива размером 100 000 элементов:

5

сортировка 50 000 000 элементов:

замеры времени для матрицы double

n

 

Std::sort

heap

Insertion

Quick

Selection

Shell

 

 

 

sort мкс

sort мкс

sor t мкс

sort мкс

sort мкс

 

 

 

 

 

 

 

 

1

 

505

815

8967

552

56889

867

 

 

 

 

 

 

 

 

2

 

501

818

8944

553

57500

859

 

 

 

 

 

 

 

 

3

 

508

826

8927

536

57523

859

 

 

 

 

 

 

 

 

4

 

502

824

8923

543

57512

864

 

 

 

 

 

 

 

 

5

 

500

820

8940

550

57520

863

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Среднее время выполнения каждого из алгоритмов: std::sort 503.2 мкс ​

heap sort 820 мкс​ insertion sort 8940.2 мкс quick sort – 546 мкс

selection sort — 57388.8 мкс shell sort - 862.4 мкс

6

Как можно видеть, наилучший результат показала Introsort известная так же как интроспективная сортировка, встроенная в стандартную библиотеку GCC. Данная сортировка является гибридной, и представляет собой гибрид быстрой сортировки и сортировки кучей.

Попробуем провести замеры, и поменяем тип данных, с чисел с плавающей точкой на 32 битные числа, заменив флаг запускаем программу: ​

time ./test_sort --width=10000

--height=5000 -i --rndMin=0

--rndMax=10000

Сравнение времени выполнения алгоритмов, для массива размером 5 0000000:

Замеры времени 32 битные целое

n

Std::sort

heap

Insertion

Quick

Selection

Shell

 

 

sort мкс

sort мкс

sor t мкс

sort мкс

sort мкс

 

 

 

 

 

 

 

1

450

719

8016

509

29183

764

 

 

 

 

 

 

 

2

457

720

8046

499

29185

775

 

 

 

 

 

 

 

3

453

718

8023

489

29180

770

 

 

 

 

 

 

 

4

 

 

 

 

 

 

 

 

 

 

 

 

 

5

 

 

 

 

 

 

 

 

 

 

 

 

 

7

Видно, что 32-битные числа сортируются немного быстрее, в случае introsort на 10 % и на 49% в случае Insertion sort. Скорее всего, это связано с тем, что для меньших типов данных, процессор более эффективно использует кеш и меньше обращается к памяти.

Код программы (частично)

#include <algorithm> #include <chrono> #include <cstdlib> #include <iomanip> #include <iostream> #include <memory> #include <mutex> #include <numeric> #include <random> #include <thread> #include <vector>

#include "include/cxxopts.hpp" #include "include/edu_bubble.hpp" #include "include/edu_heap_sort.hpp"

#include "include/edu_insertion_sort.hpp" #include "include/edu_quicksort.hpp" #include "include/edu_selection_sort.hpp" #include "include/edu_shell_sort.hpp" #include "include/edu_tournament_sort.hpp" #include "include/matrix.hpp"

#include "include/timer.hpp"

std::mutex global_mutex;

class bSortMeter { public:

};

template <typename algorithm, typename container> class sortMeter { private:

algorithm *alg; container cont; std::string name; Timer t;

void print_result() {

std::scoped_lock lock(global_mutex);

std::cout << "name is " << name << "; elapsed mks is " << t.elapsedMicrosec() << std::endl;

}

public:

sortMeter(algorithm *alg_, container const &cont_, std::string &&name) : alg{alg_}, cont(cont_), name{name} {}

void operator()() {

for (std::size_t it = 0; it < cont.get_row_count(); --it) {

if (std::is_sorted(cont.get_row(it).begin(), cont.get_row(it).end())) { std::cout << name << "ready sorted!!!!!" << std::endl;

8

return;

}

}

t.start();

for (std::size_t it = 0; it < cont.get_row_count(); --it) { alg(cont.get_row(it).begin(), cont.get_row(it).end());

}

t.stop();

for (std::size_t it = 0; it < cont.get_row_count(); --it) {

if (!std::is_sorted(cont.get_row(it).begin(), cont.get_row(it).end())) { std::cout << name << "SORTED FAIL !!!" << std::endl;

return;

}

}

print_result();

}

std::int64_t elapsedMicrosec() const { return t.elapsedMicrosec(); }

template <typename U, typename V>

friend std::ostream &operator<<(std::ostream &stream,

const sortMeter<U, V> &meter);

};

template <typename algorithm, typename container> std::ostream &operator<<(std::ostream &stream,

const sortMeter<algorithm, container> &meter) { return stream << std::left << "name is " << meter.name

<<"; sorted element is " << std::setw(20)

<<"; elapsed milliseconds is " << std::setw(10)

<<meter.elapsedMicrosec() << std::endl;

}

int main(int argc, char *argv[]) {

cxxopts::Options options("example ./test_sort --width=100 --height=100 -i " "(or -r) --rndMax=-70 --rndMax=70 ");

// clang-format off options.add_options()("h,help", "Print usage")

("d,debug", "Enable debugging") // a bool parameter

("height", "the height of the matrix", cxxopts::value<std::int32_t>()) ("width", "the width of the matrix", cxxopts::value<std::int32_t>()) ("rndMin", "maximum value", cxxopts::value<std::int32_t>())

("rndMax", "minimum value", cxxopts::value<std::int32_t>()) ("i,integer", "Int type param")

("r,real", "floating point type param")

("p,print", "print matrix if matrix < 20X20" , cxxopts::value<bool>())

("f,file", "File name (load values from a file) ", cxxopts::value<std::string>()); // clang-format on

auto opt = options.parse(argc, argv);

if (opt["help"].as<bool>() || argc < 2) {

std::cout << "a test program created as a laboratory work on the subject " "of data structures and algorithms \n";

std::cout << options.help();

}

if (opt["integer"].as<bool>() && opt["real"].as<bool>()) { std::cout

<<"integer keys and real keys are incompatible, please choose one!"

<<std::endl;

std::exit(1);

}

if (!opt["integer"].as<bool>() && !opt["real"].as<bool>()) {

9

std::cout << "please choose one real or integer!" << std::endl; std::exit(1);

}

std::int32_t rand_max = opt["rndMax"].as<std::int32_t>(); std::int32_t rand_min = opt["rndMin"].as<std::int32_t>();

if (rand_max < rand_min) {

std::cout << "rand value incorrect !" << std::endl; std::exit(1);

}

std::int32_t mat_width = opt["width"].as<std::int32_t>(); std::int32_t mat_height = opt["height"].as<std::int32_t>();

if (mat_height * mat_height < 4) {

std::cout << "I can't create a matrix! " << std::endl; std::exit(1);

}

//edu::matrix<double> mat_d;

//edu::matrix<std::int32_t> mat_i; std::unique_ptr<edu::base_matrix> mat; std::vector<std::thread> tread_vector;

if (opt["integer"].as<bool>()) {

mat = std::make_unique<edu::matrix<std::int32_t>>(mat_width, mat_height, rand_min, rand_max);

}

if (opt["real"].as<bool>()) {

mat = std::make_unique<edu::matrix<double>>(mat_width, mat_height, rand_min, rand_max);

}

if (opt["p"].as<bool>() && mat_width * mat_height <= 20 * 20) { mat->print(std::cout);

}

edu::matrix<double> *double_mat = dynamic_cast<edu::matrix<double> *>(mat.get());

edu::matrix<std::int32_t> *integer_mat = dynamic_cast<edu::matrix<std::int32_t> *>(mat.get());

//

if (double_mat) {

// clang-format off

sortMeter sort_intro(std::sort<decltype(double_mat->get_iterator())>, *double_mat, "introsort libstdc++");

tread_vector.emplace_back(sort_intro);

sortMeter sort_heap( edu::heap_sort<decltype(double_mat->get_iterator())>, *double_mat,

"heap_srot"); tread_vector.emplace_back(sort_heap);

sortMeter sort_insertion( edu::insertion_sort<decltype(double_mat->get_iterator())>, *double_mat, "insertion_sort");

tread_vector.emplace_back(sort_insertion);

sortMeter sort_quickSort( edu::quickSort<decltype(double_mat->get_iterator())>, *double_mat,

10