- •Алгоритмы поиска и сортировки. Сортировки: выбором, обменом, вставкой. Анализ сложности алгоритмов на примере сортировок. Простой и бинарный поиск.
- •Оценка алгоритмов сортировки
- •Классификация алгоритмов сортировок
- •Сортировка выбором
- •Void selectSort(t* arr, int size)
- •Сортировка пузырьковым всплытием (обменом)
- •Void bubbleSort(t* arr, int size)
- •If(pr) break;
- •Шейкерная (перемешиванием) сортировка
- •Void ShakerSort(t* arr, int start, int n)
- •Int left, right, I;
- •Сортировка вставками
- •Void insertSort(t* a, int size)
- •// Поиск места элемента в готовой последовательности
- •Быстрая сортировка
- •Рассмотрим алгоритм подробнее.
- •Общий алгоритм
- •Void quickSortR(t* a, long n) {
- •Модификации кода и метода
- •Void qsortR(t *a, long size) {
- •InsertSort(a, size);
- •Итеративная QuickSort
- •Void qSortI(t a[], long size)
- •Сортировка слиянием
- •Void Merging_Sort (t *a, int n){
- •Сортировка методом Шелла
- •Void Shell_Sort (t *a, int n)
- •Алгоритмы поисков в массивах
- •Линейный поиск (поиск в лоб) в массивах
- •Двоичный поиск (дихотомия)
Сортировка слиянием
Алгоритм сортировки слиянием был изобретен Джоном фон Нейманом в 1945 году. Он является одним из самых быстрых способов сортировки.
Слияние – это объединение двух или более упорядоченных массивов в один упорядоченный.
Сортировка слиянием является одним из самых простых алгоритмов сортировки (среди быстрых алгоритмов).
Особенностью этого алгоритма является то, что он работает с элементами массива преимущественно последовательно, благодаря чему именно этот алгоритм используется при сортировке в системах с различными аппаратными ограничениями (например, при сортировке данных на жестком диске).
Кроме того, сортировка слиянием является алгоритмом, который может быть эффективно использован для сортировки таких структур данных, как связанные списки.
Данный алгоритм применяется тогда, когда есть возможность использовать для хранения промежуточных результатов память, сравнимую с размером исходного массива.
Сначала задача разбивается на несколько подзадач меньшего размера. Затем эти задачи решаются с помощью рекурсивного вызова или непосредственно, если их размер достаточно мал.
Далее их решения комбинируются, и получается решение исходной задачи.
Процедура слияния требует два отсортированных массива. Заметим, что массив из одного элемента по определению является отсортированным.
Алгоритм сортировки слиянием
Шаг 1. Разбить имеющиеся элементы массива на пары и осуществить слияние элементов каждой пары, получив отсортированные цепочки длины 2 (кроме, быть может, одного элемента, для которого не нашлось пары).
Шаг 2. Разбить имеющиеся отсортированные цепочки на пары, и осуществить слияние цепочек каждой пары.
Шаг 3. Если число отсортированных цепочек больше единицы, перейти к шагу 2.
Рис. Демонстрация сортировки слиянием по неубыванию
//Описание функции сортировки слиянием
template <class T>
Void Merging_Sort (t *a, int n){
int i, j, //текущие индексы первого и второго сортированных
// подмассивов
k, //количество элементов в сортированных подмассивах
t, // индекс первого символа в первом подмассиве
s, //индекс массива вспомагательного
Fin1, //индекс первого элемента во втором подмассиве
Fin2; // индекс первого символа в первом подмассиве следующей
// группы подмассивов
T* tmp = new T[n]; //динамический массив того же размера
k = 1; // кол. элементов в сортированных слияемых подмассивах
while (k < n){ //1
t = 0; s = 0;
while (t+k < n){ //2 пока есть второй подмассив
Fin1 = t+k; // номер индекса первого элемента второго подмассива
Fin2 = (t+2*k < n ? t+2*k : n); //номер индекса первого эл. первого //подмассива следующей группы слияемых подмассивов
i = t; j = Fin1; // индексы на начало первого и второго подмассивов
for ( ; i < Fin1 && j < Fin2 ; s++){ // 3 пока мы в пределах обоих
//массивов
if (a[i] < a[j]) {
tmp[s] = a[i]; //заполняем динамический массив
i++;
}
else {
tmp[s] = a[j];
j++;
}
}//3
for ( ; i < Fin1; i++, s++) //если остались эл. в первом массиве
tmp[s] = a[i];
for ( ; j < Fin2; j++, s++) //если остались эл. во втором массиве
tmp[s] = a[j];
t = Fin2; // t присваивается индекс первого элемента первого
// подмассива следующей группы
}//2
//прошли все группы и теперь в сортированных массивах в 2 раза больше элементов
k *= 2;
for (s = 0; s < t; s++)
a[s] = tmp[s];
}//1
delete(tmp);
}
Недостаток алгоритма заключается в том, что он требует дополнительную память размером порядка n (для хранения вспомогательного массива).
Кроме того, он не гарантирует сохранение порядка элементов с одинаковыми значениями. Но его сложность всегда пропорциональна O(n log n).
//-------------------------------------------------------------------------------------------------
