Понятие сортировки
Сортировка - перестановка элементов в подмножестве данных по какому-либо критерию. Чаще всего в качестве критерия используется некоторое числовое поле, называемое ключевым. Цель сортировки — облегчить последующий поиск элементов в отсортированном множестве при обработке данных.
Все алгоритмы сортировки делятся на:
алгоритмы внутренней сортировки (сортировка массивов);
алгоритмы внешней сортировки (сортировка файлов).
Внутренняя сортировка оперирует массивами, целиком помещающимися в оперативной памяти с произвольным доступом к любой ячейке. Данные обычно упорядочиваются на том же месте без дополнительных затрат. (Примечание: В современных архитектурах персональных компьютеров широко применяется подкачка и кэширование памяти. Алгоритм сортировки должен хорошо сочетаться с применяемыми алгоритмами кэширования и подкачки).
Внутренняя сортировка – это алгоритм сортировки, который в процессе упорядочивания данных использует только оперативную память (ОЗУ) компьютера.
Внешняя сортировка – это алгоритм сортировки, который при проведении упорядочивания данных использует внешнюю память, как правило, жесткие диски. Внешняя сортировка разработана для обработки больших списков данных, которые не помещаются в оперативную память. Обращение к различным носителям накладывает некоторые дополнительные ограничения на данный алгоритм: доступ к носителю осуществляется последовательным образом, то есть в каждый момент времени можно считать или записать только элемент, следующий за текущим; объем данных не позволяет им разместиться в ОЗУ.
Внешняя сортировка – это алгоритм сортировки, который при проведении упорядочивания данных использует внешнюю память, как правило, жесткие диски.
Метод «Разделяй и властвуй» (англ. divide and conquer) в информатике — важная парадигма разработки алгоритмов, заключающаяся в рекурсивном разбиении решаемой задачи на две или более подзадачи того же типа, но меньшего размера, и комбинировании их решений для получения ответа к исходной задаче; разбиения выполняются до тех пор, пока все подзадачи не окажутся элементарными.
Методы сортировки
Внутренние сортировки
Сортировка слиянием
Сортировка слиянием (англ. merge sort) — алгоритм сортировки, который упорядочивает списки (или другие структуры данных, доступ к элементам которых можно получать только последовательно) в определённом порядке.
Для решения задачи сортировки эти три этапа выглядят так:
Сортируемый массив разбивается на две части примерно одинакового размера;
Каждая из получившихся частей сортируется отдельно, например — тем же самым алгоритмом;
Два упорядоченных массива половинного размера соединяются в один.
1.1. — 2.1. Рекурсивное разбиение задачи на меньшие происходит до тех пор, пока размер массива не достигнет единицы (любой массив длины 1 можно считать упорядоченным).
3.1. Соединение двух упорядоченных массивов в один. Основную идею слияния двух отсортированных массивов можно объяснить на следующем примере. Пусть мы имеем два уже отсортированных по неубыванию подмассива. Тогда: 3.2. Слияние двух подмассивов в третий результирующий массив. На каждом шаге мы берём меньший из двух первых элементов подмассивов и записываем его в результирующий массив. Счётчики номеров элементов результирующего массива и подмассива, из которого был взят элемент, увеличиваем на 1. 3.3. «Прицепление» остатка. Когда один из подмассивов закончился, мы добавляем все оставшиеся элементы второго подмассива в результирующий массив.
Реализация на С++ (сортировка по возрастанию):
const int nmax = 1000;
void Merge(int* arr, int begin, int end)
{
int i = begin,
t = 0,
mid = begin + (end - begin) / 2,
j = mid + 1,
d[nmax];
while (i <= mid && j <= end) {
if (arr[i] <= arr[j]) {
d[t] = arr[i]; i++;
}
else {
d[t] = arr[j]; j++;
}
t++;
}
while (i <= mid) {
d[t] = arr[i]; i++; t++;
}
while (j <= end) {
d[t] = arr[j]; j++; t++;
}
for (i = 0; i < t; i++)
arr[begin + i] = d[i];
}
void MergeSort(int *arr, int left, int right)
{
int temp;
if (left<right)
if (right - left == 1) {
if (arr[right]<arr[left]) {
temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
}
else {
MergeSort(arr, left, left + (right - left) / 2);
MergeSort(arr, left + (right - left) / 2 + 1, right);
Merge(arr, left, right);
}
}
Достоинства:
Работает даже на структурах данных последовательного доступа.
Хорошо сочетается с подкачкой и кэшированием памяти.
Неплохо работает в параллельном варианте: легко разбить задачи между процессорами поровну, но трудно сделать так, чтобы другие процессоры взяли на себя работу, в случае если один процессор задержится.
Не имеет «трудных» входных данных.
Устойчивая - сохраняет порядок равных элементов (принадлежащих одному классу эквивалентности по сравнению).
Недостатки:
На «почти отсортированных» массивах работает столь же долго, как на хаотичных.
Требует дополнительной памяти по размеру исходного массива.
