
СиАОД_1-4.docx
.pdf
Федеральное агентство связи Ордена Трудового Красного Знамени
Федеральное государственное бюджетное образовательное учреждение высшего образования
«Московский технический университет связи и информатики»
Кафедра Математической Кибернетики и Информационных Технологий
Отчет по курсовй работе
по предмету «СиАОД»
на темы:
«Методы сортировки» , «Методы поиска», «Рекурсия», «Алгоритмы поиска подстроки»
Выполнил: студент группы БВТ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