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

Сортировка Шелл.

Представляет собой модификацию метода вставок. Используются сравнения и перестановки элементов, но в отличие от метода вставок, в сравнении участвуют не соседние, а отстоящие друг от друга на определенном расстоянии элементы. При необходимости перестановки, элементы перемещаются скачком на данное расстояние, а не на одну позицию.

В одной из модификаций метода (в случае, предложенном Д. Шеллом) шаг кратен степеням двойки. Вначале последовательность из N элементов делится на N/2 групп, если N – четно, и на (N-1)/2 групп, если N – нечетно. Каждая группа содержит по два элемента, если количество элементов было нечетным, одна из групп содержит три элемента. Элементы каждой группы отстоят друг от друга на расстоянии N/2 или (N-1)/2. В течение первого прохода осуществляется упорядочение элементов каждой группы методом вставок. Для осуществления следующего прохода шаг уменьшается вдвое (как и число групп), по отношению к предыдущему шагу (у дробных чисел берется целая часть). Процесс повторяется до тех пор, пока шаг не станет равным единице. В этом случае методом вставок сортируется весь список (одна группа). С точки зрения программной реализации потребуется неоднократный вызов сортировки вставками с указанием, в качестве параметров (помимо исходного списка и числа элементов), индекса начального элемента группы и шага. Приблизительное число сравнений составляет N log2 N.

// Функция сортировки Шелла целочисленного массива

// Аргументы:

// arr - сортируемый массив

// size - размер сортируемого массива

void SortShell(int* arr, int size) {

int step = size / 2;

while (step != 0) {

// Сортируем группы элементов отстоящих друг от друга на значение шага вставками

for (int i = step; i < size; ++i) {

int tmp = arr[i];

int j;

for (j = i - step; j >= 0 && arr[j] > tmp; j -= step)

arr[j + step] = arr[j];

arr[j + step] = tmp;

}

step /= 2;

}

}

Сортировка выбором

В процессе первого прохода в исходном массиве находятся минимальный элемент, который помещается на место первого элемента. Первый элемент помещается на место минимального. На втором и последующих проходах поиск и обмен повторяются для оставшихся после предыдущего прохода элементов (с позициями: на втором проходе – со второй по последнюю, на третьем проходе – с третьей по последнюю и т.д.) до тех пор, пока не будет отсортирована вся последовательность. Общее число сравнений составляет приблизительно 0,5 N2, N – здесь и далее число элементов.

void selectSort(int a[], long size) {

long i, j, k;

int x;

for( i=0; i < size; i++) { // i - номер текущего шага

k=i; x=a[i];

for( j=i+1; j < size; j++) // цикл выбора наименьшего элемента

if ( a[j] < x ) {

k=j; x=a[j]; // k - индекс наименьшего элемента

}

a[k] = a[i]; a[i] = x; // меняем местами наименьший с a[i]

}

}

Сортировка пузырьком

В процессе сортировки производится попарное сравнение соседних элементов. Если порядок следования соседних элементов нарушен, то они меняются местами. В процессе первого прохода максимальный элемент попадает на последнее место и, следовательно, в последующих сравнениях не участвует. Остальные элементы "всплывают" на одну позицию вверх (поэтому метод часто называют сортировкой "пузырьком"). На каждом следующем проходе рассматривается последовательность для N-1, N-2 и т.д. элементов. Если при каком-либо проходе не было произведено ни одной перестановки, последовательность отсортирована. Максимальное число сравнений составляет приблизительно 0,5 N2, среднее число сравнений пропорционально 0,25 N2, среднее число обменов – 0,25 N2.

void bubbleSort(int a[], long size) {

long i, j;

int x;

for( i=0; i < size; i++) { // i - номер прохода

for( j = size-1; j > i; j-- ) { // внутренний цикл прохода

if ( a[j-1] > a[j] ) {

x=a[j-1]; a[j-1]=a[j]; a[j]=x;

}

}

}

}

Сортировка вставками

Первый элемент исходного списка считается отсортированным списком длины 1. Двухэлементный отсортированный список создается добавлением второго элемента исходного списка в нужное место одноэлементного списка, содержащего первый элемент. В целом, каждый новый элемент вставляется в подходящее место среди ранее упорядоченных элементов. Среднее число сравнений пропорционально N2.

void insertSort(int a[], long size) {

int x;

long i, j;

for ( i=0; i < size; i++) { // цикл проходов, i - номер прохода

x = a[i];

// поиск места элемента в готовой последовательности

for ( j=i-1; j>=0 && a[j] > x; j--)

a[j+1] = a[j]; // сдвигаем элемент направо, пока не дошли

// место найдено, вставить элемент

a[j+1] = x;

}

}

Метод подсчёта

Метод основан на том, что k+1-ый элемент упорядоченной последовательности превышает ровно k элементов, и следовательно занимает k+1-ую позицию. В процессе сортировки на каждом i-ом проходе i-ый элемент исходной последовательности попарно сравнивается со всеми остальными элементами. Инициализированный нулем перед началом прохода счетчик k увеличивается, если i-ый элемент оказался больше текущего. Таким образом, порядковый номер i-го элемента, по окончанию i-го прохода, равен k+1. Для сортировки последовательности из N элементов требуется N проходов, на каждом из которых выполняется N сравнений. Число сравнений равно N2. Приведенный метод подсчета можно использовать,

void insertSort(int a[], long size)

{

int k=0;

int *b=new int[size];

for (int i=0;i<size;i++){

for (int j=0;j<size;j++){

if (a[i]>a[j]){

k++;

}

}

b[k+1]=a[i];

k=0;

}

}

Сортировка по дереву (6)

Процесс сортировки состоит из: фазы построения двоичного дерева поиска и фазы обхода. Структура двоичного дерева задается с помощью связного списка, каждый элемент которого может иметь, максимум, двух потомков (две ссылки). Двоичное дерево формируется по всем исходным элементам, по следующему правилу. Первый элемент исходной последовательности является первым узлом дерева. Следующий элемент последовательности сравнивается со значениями в узлах строящегося дерева, начиная с корня. Если значение текущего элемента больше значения элемента в узле дерева, следует переместиться вниз по правой ссылке от текущего узла, в противном случае – по левой ссылке. Перемещение по дереву продолжается до тех пор, пока не будет достигнута свободная ссылка, после чего осуществляется вставка элемента в дерево. После формирования дерева необходимо провести процедуру смешанного обхода. Он заключается в рекурсивном посещении (чтении) узлов, начиная с корня: левого поддерева, узла, правого поддерева. В результате получается отсортированная последовательность. Среднее число сравнений aN log2 N, 1 < a < 2.

Сбалансированное N-ленточное слияние

Общей формой внешней сортировки является N-ленточное слияние. Для N-ленточного слияния потребуется 2N магнитных лент и 2N лентопротяжных устройств (которые можно заменить 2N файлами на устройстве внешней памяти). Исходная неупорядоченная последовательность размещается на первой магнитной ленте. Затем она разносится на N магнитных лент по следующему правилу: первая запись – на первую из N лент, вторая – на вторую, (N+1)-ая – снова на первую из N лент.

Сбалансированное N-ленточное слияние осуществляется в два этапа. На первом этапе из записей, хранящихся на каждой магнитной ленте, формируются упорядоченные цепочки. Так как все цепочки имеют одинаковую длину, слияние называется сбалансированным. Упорядочение цепочки происходит в оперативной памяти одним из методов внутренней сортировки. Упорядоченные цепочки размещаются на N свободных магнитных лентах, после чего начинается второй этап сортировки – слияние. Процесс слияния осуществляется в несколько циклов. После каждого цикла слияния длина упорядоченных цепочек увеличивается на N. В конечном итоге, формируется упорядоченная последовательность из N составляющих. Собственно слияние осуществляется следующим образом. Пусть имеются две цепочки длиной l, изначально упорядоченные. Необходимо получить одну упорядоченную цепочку. Для этого: сравниваются первые элементы двух цепочек, меньшая переписывается в результирующую цепочку; операция осуществляется с помощью трех счетчиков; после записи в результирующую последовательность увеличивается на единицу счетчик результирующей последовательности и счетчик последовательности, в которой был обнаружен меньший элемент; действие повторяется до тех пор, пока один из счетчиков исходной последовательности не достигнет значения конца последовательности, после чего оставшиеся элементы другой последовательности дописываются в конец результирующей. Таким образом, будут упорядочены каждая из N магнитных лент.