Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Билеты на зачет.docx
Скачиваний:
51
Добавлен:
01.06.2015
Размер:
554.66 Кб
Скачать

Y 1 2 3 4 5 6 7 8

Чтобы не запутаться в двух виртуальных массивах, будем использовать один массив двойной длины array[1..2*n]. При этом сначала исходный массив находится в первой половине, в выходной – во второй, а затем наоборот.

Заведем булевскую переменную Up, которая определяет направление слияния: true – из первой половины во вторую, false – из второй половины в первую. Индексы i, j - отвечают за место, из которого берутся элементы для слияния, а k, l – за место куда пересылаются элементы. Переменная Pопределяет длину сливаемых серий (1, 2, 4, …).

Procedure merge(var x: vector);

Var up: boolean;

I, j, k, l: integer;

P: integer;

Begin

Up:=true;

p:=1;

Repeat

if up then

Begin i:=1;j:=n; k:=n+1; l:=2*n; end

Else

Begin i:=n+1; j:=2*n; k:=1; l:=n end;

{слияние p-серии из i, j в к, l}

Up:=not up;

P:=2*p

Until p>=n;

Слияние происходит следующим образом: сначала пересылка идет по адресу k, при этом индекс увеличивается на единицу, затем по адресуl, и индекс уменьшается на 1. Для упрощения будем считать, что пересылка всегда идет по адресуkс шагомh, но после каждого слияния будем чередоватьh(либо +1, либо -1), а также менять местами значенияkиl.

h:=1; m:=n;

Repeat

q:=p; r:=p; m:=m-2*p;

{слияние q элементов из i и r элементов из j}

h:=-h;

{обмен k, l};

Until m=0;

Сама процедура слияния должна предусмотреть копирование оставшегося остатка:

While (q<>0) and(r<>0) do

if x[i]<x[j]

then begin x[k]:=x[i]; k:=k+h; i:=i+1; q:=q-1 end

Else begin x[k]:=x[j]; k:=k+h; j:=j-1; r:=r-1 end;

{копирование остатков из i или j}

Окончательный текст программы

Procedure merge(var x: vector);

Var up: boolean;

I, j, k, l, t: integer;

P, h, q, r, m: integer;

Begin

Up:=true;

p:=1;

Repeat

m:=n; {общее число элементов во входных последовательностях, которые осталось слить}

H:=1;

if up then

Begin i:=1;j:=n; k:=n+1; l:=2*n; end

Else

Begin i:=n+1; j:=2*n; k:=1; l:=n end;

Repeat

if m>= p then q:=p else q:=m; m:=m-q;

if m>= p then r:=p else r:=m; m:=m-r;

While (q<>0) and(r<>0) do

if x[i]<x[j]

then begin x[k]:=x[i]; k:=k+h; i:=i+1; q:=q-1 end

Else begin x[k]:=x[j]; k:=k+h; j:=j-1; r:=r-1 end;

{копирование остатков}

While r<>0 do

Begin

A[k]:=a[j]; k:=k+h; j:=j-1; r:=r-1

End;

While q<>0 do

Begin

A[k]:=a[i]; k:=k+h; i:=i+1; q:=q-1

End;

H:=-h;

T:=k; k:=l; l:=t;

Until m=0;

Up:=not up;

P:=2*p

Until p>=n;

if not up then for i:=1 to n do x[i]:=x[i+n]

End;

Поскольку на каждом проходе pудваивается, то сортировка требует [log2N] проходов. При каждом проходе перемещаются всеNэлементов. Поэтому характеристикаMдля сортировки слиянием оценивается какN*[log2N]. Число сравненийCменьше, чем М, так как при копировании остатков сравнения не проводятся.

Естественное двухпутевое слияние

В случае простого слияния серии формируются из фиксированного числа элементов (2,4,8), при этом никак не учитывается, что данные могут быть уже частично отсортированы естественным образом.

Если сформировать серии таким образом, чтобы они образовывали естественным образом упорядоченные последовательности, то слияние будет выглядеть так:

X1 7 3 6 4 9 8 5

Y1 5 7 8 9 6 4 3

X1 3 4 5 6 7 8 9

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]