Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Алгоритмы ответы экзамен.docx
Скачиваний:
14
Добавлен:
05.08.2019
Размер:
1.69 Mб
Скачать
  1. Метод разделяй и властвуй при построении алгоритмов, пример алгоритма

Если алгоритм рекурсивно обращается к самому себе, время его работы часто

описывается с помощью рекуррентного уравнения, или рекуррентного соотношения, в котором полное время, требуемое для решения всей задачи с объемом ввода n, выражается через время решения вспомогательных подзадач. Затем данное рекуррентное уравнение решается с помощью определенных математических методов, и устанавливаются границы производительности алгоритма.

Получение рекуррентного соотношения для времени работы алгоритма, основанного на принципе "разделяй и властвуй", базируется на трех этапах, соответствующих парадигме этого принципа. Обозначим через T (n) время решения задачи, размер которой равен п. Если размер задачи достаточно мал, скажем, n ≤ c, где с — некоторая заранее известная константа, то задача решается непосредственно в течение определенного фиксированного времени, которое мы обозначим через . Предположим, что наша задача делится на а подзадач, объем каждой из которых равен 1/Ь от объема исходной задачи.

Если разбиение задачи на вспомогательные подзадачи происходит в течение времени D (n), а объединение решений подзадач в решение исходной задачи — в течение времени С (n), то мы получим такое рекуррентное соотношение:

пример алгоритма сортировка слиянием

public void merge(int []arr, long left, long middle, long right) {

// Слияние упорядоченных частей массива в буфер temp

// с дальнейшим переносом содержимого temp в a[left]...a[right]

// текущая позиция чтения из первой последовательности a[left]...a[middle]

long pos1=left;

// текущая позиция чтения из второй последовательности a[middle+1]...a[right]

long pos2=middle+1;

// текущая позиция записи в temp

long pos3=0;

int[] temp = new int[right-left+1];

// идет слияние, пока есть хоть один элемент в каждой последовательности

while (pos1 <= middle && pos2 <= right)

{

if (arr[pos1] < arr[pos2])

temp[pos3++] = arr[pos1++];

else

temp[pos3++] = arr[pos2++];

}

// одна последовательность закончилась -

// копировать остаток другой в конец буфера

while (pos2 <= right) // пока вторая последовательность непуста

temp[pos3++] = arr[pos2++];

while (pos1 <= middle) // пока первая последовательность непуста

temp[pos3++] = arr[pos1++];

// скопировать буфер temp в a[lb]...a[ub]

for (pos3 = 0; pos3 < right - left + 1; pos3++)

arr[left + pos3] = temp[pos3];

}

//a - сортируемый массив, его левая граница left, правая граница right

void mergeSort(int[] arr, long left, long right)

{

long middle; // индекс, по которому делим массив

if (left < right) // если есть более 1 элемента

{

middle = (left + right) / 2;

mergeSort(arr, left, middle); // сортировать левую половину

mergeSort(arr, middle+1, right); // сортировать правую половину

merge(arr, left, middle, right); // слить результаты в общий массив

}

}