Алгоритмы сортировки массивов. Внешняя сортировка
Сортировка естественным слиянием
В случае простого слияния частичная упорядоченность сортируемых данных не дает никакого преимущества. Это объясняется тем, что на каждом проходе сливаются серии фиксированной длины. При естественном слиянии длина серий не ограничивается, а определяется количеством элементов в уже упорядоченных подпоследовательностях, выделяемых на каждом проходе.
Сортировка, при которой всегда сливаются две самые длинные из возможных последовательностей, является естественным слиянием. В данной сортировке объединяются серии максимальной длины.
Алгоритм сортировки естественным слиянием
Шаг 1. Исходный файл f разбивается на два вспомогательных файла f1 и f2. Распределение происходит следующим образом: поочередно считываются записи ai исходной последовательности (неупорядоченной) таким образом, что если значения ключей соседних записей удовлетворяют условию f(ai)<=f(ai+1), то они записываются в первый вспомогательный файл f1. Как только встречаются f(ai)>f(ai+1), то записи ai+1 копируются во второй вспомогательный файл f2. Процедура повторяется до тех пор, пока все записи исходной последовательности не будут распределены по файлам.
Шаг 2. Вспомогательные файлы f1 и f2 сливаются в файл f, при этом серии образуют упорядоченные последовательности.
Шаг 3. Полученный файл f вновь обрабатывается, как указано в шагах 1 и 2.
Шаг 4. Повторяя шаги, сливаем упорядоченные серии до тех пор, пока не будет упорядочен целиком весь файл.
Символ "`" обозначает признак конца серии.
Признаками конца сортировки естественным слиянием являются следующие условия:
- количество серий равно 1 (определяется на фазе слияния).
- при однофазной сортировке второй по счету вспомогательный файл после распределения серий остался пустым.
Естественное слияние, у которого после фазы распределения количество серий во вспомогательных файлах отличается друг от друга не более чем на единицу, называется сбалансированным слиянием, в противном случае – несбалансированное слияние.
//Описание функции сортировки естественным слиянием
void Natural_Merging_Sort (char *name){
int s1, s2, a1, a2, mark;
FILE *f, *f1, *f2;
s1 = s2 = 1;
while ( s1 > 0 && s2 > 0 ){
mark = 1;
s1 = 0;
s2 = 0;
f = fopen(name,"r");
f1 = fopen("nmsort_1","w");
f2 = fopen("nmsort_2","w");
fscanf(f,"%d",&a1);
if ( !feof(f) ) {
fprintf(f1,"%d ",a1);
}
if ( !feof(f) ) fscanf(f,"%d",&a2);
while ( !feof(f) ){
if ( a2 < a1 ) {
switch (mark) {
case 1:{fprintf(f1,"' "); mark = 2; s1++; break;}
case 2:{fprintf(f2,"' "); mark = 1; s2++; break;}
}
}
if ( mark == 1 ) { fprintf(f1,"%d ",a2); s1++; }
else { fprintf(f2,"%d ",a2); s2++;}
a1 = a2;
fscanf(f,"%d",&a2);
}
if ( s2 > 0 && mark == 2 ) { fprintf(f2,"'");}
if ( s1 > 0 && mark == 1 ) { fprintf(f1,"'");}
fclose(f2);
fclose(f1);
fclose(f);
cout << endl;
Print_File(name);
Print_File("nmsort_1");
Print_File("nmsort_2");
cout << endl;
f = fopen(name,"w");
f1 = fopen("nmsort_1","r");
f2 = fopen("nmsort_2","r");
if ( !feof(f1) ) fscanf(f1,"%d",&a1);
if ( !feof(f2) ) fscanf(f2,"%d",&a2);
bool file1, file2;
while ( !feof(f1) && !feof(f2) ){
file1 = file2 = false;
while ( !file1 && !file2 ) {
if ( a1 <= a2 ) {
fprintf(f,"%d ",a1);
file1 = End_Range(f1);
fscanf(f1,"%d",&a1);
}
else {
fprintf(f,"%d ",a2);
file2 = End_Range(f2);
fscanf(f2,"%d",&a2);
}
}
while ( !file1 ) {
fprintf(f,"%d ",a1);
file1 = End_Range(f1);
fscanf(f1,"%d",&a1);
}
while ( !file2 ) {
fprintf(f,"%d ",a2);
file2 = End_Range(f2);
fscanf(f2,"%d",&a2);
}
}
file1 = file2 = false;
while ( !file1 && !feof(f1) ) {
fprintf(f,"%d ",a1);
file1 = End_Range(f1);
fscanf(f1,"%d",&a1);
}
while ( !file2 && !feof(f2) ) {
fprintf(f,"%d ",a2);
file2 = End_Range(f2);
fscanf(f2,"%d",&a2);
}
fclose(f2);
fclose(f1);
fclose(f);
}
remove("nmsort_1");
remove("nmsort_2");
}
//определение конца блока
bool End_Range (FILE * f){
int tmp;
tmp = fgetc(f);
tmp = fgetc(f);
if (tmp != '\'') fseek(f,-2,1);
else fseek(f,1,1);
return tmp == '\'' ? true : false;
}
Листинг
.
Таким образом, число чтений или перезаписей файлов при использовании метода естественного слияния будет не хуже, чем при применении метода простого слияния, а в среднем – даже лучше. Но в этом методе увеличивается число сравнений за счет тех, которые требуются для распознавания концов серий. Помимо этого, максимальный размер вспомогательных файлов может быть близок к размеру исходного файла, так как длина серий может быть произвольной.
Ключевые термины
Внешняя сортировка – это сортировка данных, которые расположены на внешних устройствах и не вмещающихся в оперативную память.
Двухпутевое слияние – это сортировка, в которой данные распределяются на два вспомогательных файла.
Двухфазная сортировка – это сортировка, в которой отдельно реализуется две фазы: распределение и слияние.
Длина серии – это количество элементов в серии.
Естественное слияние – это сортировка, при которой всегда сливаются две самые длинные из возможных серий.
Многопутевое слияние – это сортировка, в которой данные распределяются на N (N > 2) вспомогательных файлов.
Несбалансированное слияние – это естественное слияние, у которого после фазы распределения количество серий во вспомогательных файлах отличается друг от друга более чем на единицу.
Однофазная сортировка – это сортировка, в которой объединены фазы распределения и слияния в одну.
Простое слияние – это одна из сортировок на основе слияния, в которой длина серий фиксируется на каждом шаге.
Распределение – это процесс разделения упорядоченных серий на два и несколько вспомогательных файла.
Сбалансированное слияние – это естественное слияние, у которого после фазы распределения количество серий во вспомогательных файлах отличается друг от друга не более чем на единицу.
Серия (упорядоченный отрезок) – это последовательность элементов, которая упорядочена по ключу.
Слияние – это процесс объединения двух (или более) упорядоченных серий в одну упорядоченную последовательность при помощи циклического выбора элементов доступных в данный момент.
Фаза – это действия по однократной обработке всей последовательности элементов.
Краткие итоги
- Внешние сортировки применяются к данным, которые хранятся во внешней памяти. Внешние сортировки применяются, если объем сортируемых данных превосходит допустимое место в ОЗУ.
- Внешние сортировки, по сравнению с внутренними, характеризуются проигрышем по времени за счет обращения к внешним носителям.
- К наиболее известным алгоритмам внешних сортировок относятся: сортировки слиянием (простое слияние и естественное слияние); улучшенные сортировки (многофазная сортировка и каскадная сортировка).
- Алгоритмы внешних сортировок отличаются по реализации числом фаз и путей.
- Простое слияние является одной из сортировок на основе слияния, в которой длина серий фиксируется на каждом шаге.
- Естественное слияние является сортировкой, при которой всегда сливаются две самые длинные из возможных серий.
- Число чтений или перезаписей файлов при использовании метода естественного слияния будет не хуже, чем при применении метода простого слияния, а в среднем – даже лучше. Однако в данном методе увеличивается число сравнений за счет распознавания концов серий.
