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

Одна из сортировок на основе слияния называется простым слиянием.

Алгоритм сортировки простым слияния является простейшим алгоритмом внешней сортировки, основанный на процедуре слияния серией.

В данном алгоритме длина серий фиксируется на каждом шаге. В исходном файле все серии имеют длину 1, после первого шага она равна 2, после второго – 4, после третьего – 8, после k-го шага – .

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

Шаг 1. Исходный файл f разбивается на два вспомогательных файла f1 и f2.

Шаг 2. Вспомогательные файлы f1 и f2 сливаются в файл f, при этом одиночные элементы образуют упорядоченные пары.

Шаг 3. Полученный файл f вновь обрабатывается, как указано в шагах 1 и 2. При этом упорядоченные пары переходят в упорядоченные четверки.

Шаг 4. Повторяя шаги, сливаем четверки в восьмерки и т.д., каждый раз удваивая длину слитых последовательностей до тех пор, пока не будет упорядочен целиком весь файл (рис. 1).

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

Признаками конца сортировки простым слиянием являются следующие условия:

· длина серии не меньше количества элементов в файле (определяется после фазы слияния);

· количество серий равно 1 (определяется на фазе слияния).

· при однофазной сортировке второй по счету вспомогательный файл после распределения серий остался пустым.

 

Исходный файл f: 5 7 3 2 8 4 1
  Распределение Слияние
1 проход f1: 5 3 8 1   f2: 7 2 4 f: 5 7 2 3 4 8 1    
2 проход f1: 5 7 4 8   f2: 2 3 1 f: 2 3 5 7 1 4 8    
3 проход f1: 2 3 5 7   f2: 1 4 8 f: 1 2 3 4 5 7 8    

 

Рис.1. Демонстрация сортировки двухпутевым двухфазным простым слиянием

 

//Описание функции сортировки простым слиянием

void Simple_Merging_Sort (char *name){

int a1, a2, k, i, j, kol, tmp;

FILE *f, *f1, *f2;

kol = 0;

if ( (f = fopen(name,"r")) == NULL )

printf("\nИсходный файл не может быть прочитан...");

else {

while ( !feof(f) ) {

fscanf(f,"%d",&a1);

kol++;

}

fclose(f);

}

k = 1;

while ( k < kol ){

f = fopen(name,"r");

f1 = fopen("smsort_1","w");

f2 = fopen("smsort_2","w");

if ( !feof(f) ) fscanf(f,"%d",&a1);

while ( !feof(f) ){

for ( i = 0; i < k && !feof(f) ; i++ ){

fprintf(f1,"%d ",a1);

fscanf(f,"%d",&a1);

}

for ( j = 0; j < k && !feof(f) ; j++ ){

fprintf(f2,"%d ",a1);

fscanf(f,"%d",&a1);

}

}

fclose(f2);

fclose(f1);

fclose(f);

 

f = fopen(name,"w");

f1 = fopen("smsort_1","r");

f2 = fopen("smsort_2","r");

if ( !feof(f1) ) fscanf(f1,"%d",&a1);

if ( !feof(f2) ) fscanf(f2,"%d",&a2);

while ( !feof(f1) && !feof(f2) ){

i = 0;

j = 0;

while ( i < k && j < k && !feof(f1) && !feof(f2) ) {

if ( a1 < a2 ) {

fprintf(f,"%d ",a1);

fscanf(f1,"%d",&a1);

i++;

}

else {

fprintf(f,"%d ",a2);

fscanf(f2,"%d",&a2);

j++;

}

}

while ( i < k && !feof(f1) ) {

fprintf(f,"%d ",a1);

fscanf(f1,"%d",&a1);

i++;

}

while ( j < k && !feof(f2) ) {

fprintf(f,"%d ",a2);

fscanf(f2,"%d",&a2);

j++;

}

}

while ( !feof(f1) ) {

fprintf(f,"%d ",a1);

fscanf(f1,"%d",&a1);

}

while ( !feof(f2) ) {

fprintf(f,"%d ",a2);

fscanf(f2,"%d",&a2);

}

fclose(f2);

fclose(f1);

fclose(f);

k *= 2;

}

remove("smsort_1");

remove("smsort_2");

}

Заметим, что для выполнения внешней сортировки методом простого слияния в оперативной памяти требуется расположить всего лишь две переменные – для размещения очередных элементов (записей) из вспомогательных файлов. Исходный и вспомогательные файлы будут раз прочитаны и столько же раз записаны.