Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Сортировка слияниями






Метод слияний – один из первых в теории алгоритмов сортировки. Он предложен Дж. фон Нейманом в 1945 году.

Рассмотрим следующую задачу. Объединить («слить») упорядоченные фрагменты массива A A [ k ],... A [ m ] и A [ m +1],..., A [ q ] в один A [ k ],..., A [ q ], естественно, тоже упорядоченный (k £ m £ q). Основная идея решения состоит в сравнении очередных элементов каждого фрагмента, выяснении, какой из элементов меньше, переносе его во вспомогательный массив D (для простоты) и продвижении по тому фрагменту массива, из которого взят элемент. При этом следует не забыть записать в D оставшуюся часть того фрагмента, который не успел себя «исчерпать».

Пример. Пусть первый фрагмент состоит из 4-х элементов: 2 4 6 11, а второй – из 8-и: 1 3 5 7 14 17. Рис 1. Иллюстрация слияния упорядоченных фрагментов. иллюстрирует начало объединения упорядоченных фрагментов.

Рис 1. Иллюстрация слияния упорядоченных фрагментов.

Реализация слияния фрагментов:

#include < iostream>

#include < locale.h>

using namespace std;

 

void Sl(int m[], int k, int q) // или...int *a

{

// k – нижняя граница упорядоченного фрагмента

// q – верхняя граница фрагмента

int i, j, t, mid, d[20];

i=k;

mid=k+(q-k)/2;

j=mid+1;

t=1;

while (i< =mid & & j< =q)

{

if (m[i]< =m[j]) {d[t]=m[i]; i++; }

else { d[t]=m[j]; j++; }

t++;

}

// Один из фрагментов обработан полностью, осталось перенести в D остаток другого фрагмента

while (i< =mid)

{ d[t]=m[i]; i++; t++; }

while (j< =q)

{ d[t]=m[j]; j++; t++; }

for (i=1; i< =t-1; i++) m[k+i-1]=d[i];

}

// Рекурсивная реализация сортировки слиянием

void Sort_Sl(int *m, int i, int j)

{

int t;

if (i< j)

// Обрабатываемый фрагмент массива состоит более, чем из одного элемента

if (j-i==1) {

if (m[j]< m[i])

// Обрабатываемый фрагмент массива состоит из двух элементов*)

{ t=m[i]; m[i]=m[j]; m[j]=t; }; }

else {

// Разбиваем заданный фрагмент на два

Sort_Sl(m, i, i+(j-i)/2); // рекурсивные вызовы процедуры Sort_Sl

Sort_Sl(m, i+(j-i)/2+1, j);

Sl(m, i, j);

}

}

void input(int *m, int & n) // Имя массива является адресом его начала.

{ // Или void input(int m[], int & n)

cout< < " Введите количество элементов массива ";

cin> > n;

for (int i=0; i< n; i++)

{

cout< < " a[" < < i< < " ]=";

cin> > m[i]; // Конструкция a[i] эквивалентна *(a + i)

}

 

}

void print (int *m, int n)

{

for (int i=0; i< n; i++)

cout< < m[i]< < " ";

cout< < " \n";

 

}

void main()

{

setlocale(LC_ALL, " rus");

const int nmax=20;

int n, a[nmax];

input(a, n);

cout< < " Исходный массив: \n";

print(a, n);

Sort_Sl(a, 0, n-1);

cout< < " Отсортированный массив: \n";

print(a, n);

}

Первый вызов процедуры – Sort_Sl(a, 0, n-1);, где a – исходный массив из N элементов.

Данный алгоритм работает быстрее чем, например, пузырьковая, а недостаток метода – в требовании довольно большого объема дополнительной памяти.

9. Быстрая сортировка (сортировка Хоара, 1962) [1]

Рассмотрим элемент, находящийся посередине массива М (назовем его Х). Затем начнем осуществлять два встречных просмотра массива: двигаемся слева направо, пока не найдем элемент M [ i ]> X и справа налево, пока не найдем элемент M [ j ]< X. Когда указанные элементы будут найдены, поменяем их местами и продолжим процесс " встречных просмотров с обменами", пока два идущих навстречу друг другу просмотра не встретятся. В результате массив разделится на две части: левую, состоящую из элементов меньших или равных Х, и правую, в которую попадут элементы, большие или равные Х. После такого разделения массива М, чтобы завершить его сортировку, достаточно осуществить то же самое с обеими полученными частями, затем с частями этих частей и т.д., пока каждая часть не будет содержать ровно один элемент.

Реализация указанного метода приводит к следующему (рекурсивному!) решению задачи сортировки:

void Qsort(int a[], int L, int R) // или...int *a

{ int i=L, j=R, w, x;

x=a[(L+R)/2];

do { while (a[i]< x) i++;

while (a[j]> x) j--;

if(i< =j)

{w=a[i]; a[i]=a[j]; a[j]=w;

i++; j--; }

} while (i< j);

if (L< j) Qsort(a, L, j);

if (i< R) Qsort(a, i, R);

}

void main()

{

setlocale(LC_ALL, " rus");

const int nmax=20;

int n, a[nmax];

input(a, n);

cout< < " Исходный массив: \n";

print(a, n);

Qsort(a, 0, n-1);

cout< < " Отсортированный массив: \n";

print(a, n);

}

Основная программа должна содержать вызов процедуры в виде:






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.