Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Алгоритмы и структуры данных.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
175.1 Кб
Скачать

Методы сортировки.

Сортировка – это перегруппировка заданного множества объектов в некотором определённом порядке. Различают сортировку массивов и сортировку файлов (внутреннюю и внешнюю сортировку). При внутренней сортировке все данные находятся в оперативной памяти. При внешней сортировке часть данных находится в оперативной памяти, а часть – на внешних носителях. Методы внутренних и внешних сортировок отличаются. Хорошие методы сравнений требуют n * log2n сравнений, а плохие – порядка n2 сравнений. Существуют следующие методы внутренней сортировки:

1) Обменные сортировки.

2) Сортировки вставками.

3) Сортировка посредством выбора.

4) Улучшенные методы сортировки.

Обменные сортировки.

1) Пузырьковая сортировка.

Пример: 44 55 12 42 94 18 6 67

6 44 55 12 42 94 18 67

6 12 44 55 18 42 94 67

6 12 18 44 55 42 67 94

6 12 18 42 44 55 67 94

При первом просмотре делается n-1 сравнение, при втором – n-2 сравнения и т.д.

Фрагмент программы, реализующей этот метод сортировки.

var a: array[1..n] of real;

i, j: integer; x: real;

begin

for i := 2 to n do

for j := n downto i do

if a[j – 1] > a[j] then begin

x := a[j – 1]; a[j – 1] := a[j]; a[j] := x; end;

end.

Внешний цикл – цикл по просмотрам, а внутренний – для сравнения пар элементов.

2) Шейкерная сортировка.

Пример: 44 55 12 42 94 18 6 67 L = 2, R = 8

6 44 55 12 42 94 18 67 L = 3, R = 8

6 44 12 42 55 18 67 94 L = 3, R = 7

6 12 44 18 42 55 67 94 L = 4, R = 7

var a: array[1..n] of real;

j: integer; x: real;

l, r, k: integer;

begin

l := 2; r := n; k := n;

repeat

for j := r downto l do if a[j – 1] > a[j] then begin

x := a[j – 1]; a[j - 1] := a[j]; a[j] := x; k := j; end;

l := k + 1;

for j := l to r do if a[j – 1] > a[j] then begin

x := a[j – 1]; a[j - 1] := a[j]; a[j] := x; k := j; end;

r := k – 1;

until l > r;

end.

Сортировка вставками.

При такой сортировке элементы мысленно делятся на уже отсортированную последовательность а1…аi-1 и неотсортированную. При каждом шаге, начиная с i = 2, из исходной последовательности берётся i-тый элемент и сравнивается с предшествующими i - 1 элементами для того, чтобы найти элемент, меньший, чем он сам. После чего i-тый элемент вставляется за этим элементом. Если меньший элемент, чем i-тый, не нашёлся, i-тый элемент становится самым первым.

Пример: 44 55 12 42 94 18 6 67

I = 2 44 55

I = 3 12 44 55

I = 4 12 42 44 55

I = 5 12 42 44 55 94

I = 6 12 18 42 44 55 94

I = 7 6 12 18 42 44 55 94

I = 8 6 12 18 42 44 55 67 94

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

var array[0..n] of real;

i, j: integer; x: real;

begin

for i := 2 to n do begin

x := a[i]; a[0] := x; j := i;

while x < a[j – 1] do begin

a[j] := a[j – 1]; j := j – 1; end;

a[j] := x;

end;

end.

Скорость сортировки можно несколько увеличить при использовании бинарного поиска для нахождения места вставки в отсортированной последовательности. Это уменьшает количество сравнений до n * ln n. Этот модифицированный метод получил название сортировки бинарными вставками.

var array[0..n] of real;

i, j: integer; x: real;

begin

for i := 2 to n do begin

x := a[i]; l := 0; r := i;

while l < r do begin

m := (r + l) div 2;

if x > a[m] then l := m + 1 else r := m;

end;

for j := i downto r + 1 do a[j] := a[j – 1];

a[r] := x;

end;

end.

Сортировка с помощью прямого выбора.

Алгоритм этой сортировки заключается в следующем:

1) Выбирается наименьший (наибольший) элемент.

2) Он меняется местами с первым элементом массива.

3) Этот процесс повторяется над оставшимися (n – 1) элементами, потом (n – 2) и так далее.

Фрагмент программы, который реализует этот метод сортировки.

const n = … ;

var a: array[1..n] of real;

x: real;

i, j, k: integer;

begin

for i := 1 to n – 1 do begin

k := i;

x := a[i];

for j := i + 1 to n do

if a[i] < x then begin

k := j;

x := a[k];

end;

a[k] := a[i];

a[i] := x;

end;

end.

Эта сортировка работает быстро для малого значения n.

Улучшенные методы сортировки.

В 1959 году было предложено усовершенствовать метод сортировки вставками. Этот метод получил название «Сортировка Шела».

Берётся массив и разбивается на подмассивы с некоторым шагом k. И каждый подмассив сортируется отдельно методом простых вставок. Шаг k определяет расстояние между элементами, которые включаются в подмассив. Кроме того, k определяет, сколько всего будет подмассивов. После того, как k подмассивов будет отсортировано, выбирается новое, меньшее значение шага k. И массив снова разделяется на новый набор подмассивов. Каждый из новых подмассивов снова сортируется методом простых вставок. Затем процесс повторяется с ещё меньшим значением k. В конце концов, k принимает значение 1, и тогда уже рассматривается весь массив целиком.

Пример.

Последовательность шагов: 4, 2, 1.

1) 44 55 12 42 94 18 6 67 Шаг 4

| |

- I подмасс.-

2) 44 18 6 42 94 55 12 67 Шаг 2

| | | |

--------- I ----------

3) 6 18 12 42 44 55 94 67 Шаг 1

6 12 18 42 44 55 67 94

Первая реализация этого метода сортировки. Шаги выбираются: каждый следующий вдвое меньше предыдущего.

begin

m := n;

while m >= 1 do begin

m := m div 2;

for i := m + 1 to n do begin

x := a[i];

j := i – m;

while (j >= 1) and (x < a[j]) do begin

a[j + m] := a[j];

j := j – m;

end;

a[j + m] := x;

end;

end;

end.

Вторая реализация этого метода сортировки. Длина последовательности шагов t берётся равной 4. А сами шаги: первый шаг – 9, второй – 5, третий – 3 и четвёртый – 1. В этом алгоритме необходим дополнительный массив h, который будет хранить последовательность шагов. Поскольку поиск места для включения элемента осуществляется методом барьеров, то исходный массив надо увеличить на 9 элементов, поскольку для каждого подмассива необходим свой барьер.

const t = 4;

n = … ;

h: array[1..t] of byte = (9, 5, 3, 1);

var i, j, k, s: integer;

a: array[-9..n] of real;

begin

for m := 1 to t do begin

k := h[m];

s := -k;

for i := k + 1 to n do begin

x := a[i];

j := i – k;

if s = 0 then s := -k;

s := s + 1;

a[s] := x;

while x < a[j] do begin

a[j + k] := a[j];

j := j – k;

end;

a[j + k] := x;

end;

end;

end.

Обменная сортировка с разделением. Сортировка Хоара. Быстрая сортировка.

Выбирается средний по номеру элемент массива x. Затем массив начинает просматриваться с левой стороны (с начала) до тех пор, пока не будет обнаружен элемент, который будет больше среднего. Дальше массив начинает просматриваться справа (с конца), пока не будет найден элемент меньше среднего. Потом эти элементы меняются местами. Дальше процесс продолжается до тех пор, пока оба просмотра не сойдутся в середине.

44 55 12 42 94 6 18 67

i = 1 j = 7

i = 2 j = 6

j = 3 i = 5

18 6 12 42 94 55 44 67

6 12 18 42 44 55 67 94

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

Задание. Написать программу, которая сортирует массив с помощью рассмотренных восьми методов. Каждый метод сортировки организовать в виде процедуры. В качестве параметра процедуре надо передать массив по значению. В основной программе формируется массив с помощью генератора случайных чисел. Необходимо предусмотреть вывод исходного массива на экран и вывод отсортированных массивов. Затем значение n увеличить до 2048 и для каждого метода предусмотреть счётчик числа сравнений и числа перестановок.

procedure quicksort;

const m = 12;

var i, j, l, r: integer;

x, w: real;

s: 0..m;

stack: array[1..m] of record

l, r: integer;

end;

begin

s := 1;

stack[s].l := 1;

stack[s].r := n;

repeat

l := stack[s].l;

r := stack[s].r;

s := s – 1;

repeat

i :=l; j := r;

x := a[(l + r) div 2];

repeat

while a[i] < x do i := i + 1;

while x < a[j] do j := j – 1;

if i <= j then begin

w := a[i];

a[i] := a[j];

a[j] := w;

i := i + 1; j := j + 1;

end;

until i > j;

if i < r then begin

s := s + 1;

stack[s].l := i;

stack[s].r := r;

end;

r := j;

until l >= r;

until s = 0;

end;

if (j – l) < (r – i) then begin

if i < r then begin

s := s + 1;

stack[s].l := i;

stack[s].r := r;

end;

r := j;

end

else begin

if l < j then begin

s := s + 1;

stack[s].l := l;

stack[s].r := j;

end;

end;