Моу сош с. Камышки творческая работа - страница 8

^ Приложение №10
Сортировка с разделением

Прежде чем представлять данный метод сортировки, рассмотрим такую задачу:

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

Например, массив 38, 8, 16, 6, 79, 76, 57, 24, 56, 2, 58, 48, 4, 70, 45, 47

при основном элементе, равном первому (38), после указанного преобразования может принять вид: 4, 8, 16, 6, 2, 24, 38, 57, 56, 76, 58, 48, 79, 70, 45, 47

Это можно сделать следующим образом. Используем два "указателя" — i и j;

i - ведет отсчет номеров элементов слева, а j — справа. Сначала имеем i=1, j=n (в рассматриваемом случае число элементов массива n=16). Значение основного элемента обозначим m.

Сравниваем m и a[j].Если a[jl>m, то устанавливаем j=j-l и проводим следующее сравнение m и а [j ]. Продолжаем уменьшать j до тех пор, пока не достигнем а [ j ]<=m.Тогда поменяем местами элементы а [j] и а [ i] (см. строку 5 на рис. 5, обмен значений 38 и 4), установим значение i=i+1 и,сравнивая элементы а [i ] со значением m, будем увеличивать i до тех пор, пока не получим а [ i ] >=m. После следующего обмена (строка 10, элементы со значе­ниями 79 и 38) опять уменьшим j и будем просматривать элементы справа налево и т. д. до тех пор, пока не станет j<=i.

i 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 j

38, 8, 16, 6, 79, 76, 57, 24,56, 2, 58, 48, 4, 70, 45, 47 Действие

38 47 Уменьшение j

38 45 -"-

38 70 -"-

38 4 4<38

4 38 Обмен

8 38 Увеличение i

16 38 -“-

6 38 -“-

79 38 79>38

38 79 Обмен

38 48 Уменьшение j

38 58 -"-

38 2 -"- 2<38

2 38 Обмен

76 38 Увеличение i

38 76 Обмен

38 56 Уменьшение j

38 24 -"- 24<38

24 38 Обмен

57 38 Увеличение i

38 57 Обмен

4, 8, 16, 6, 2, 24, 38, 57,56, 76, 58, 48, 79, 70, 45, 47 Рис. 5. Разделение элементов

Процедура разделения массива на школьном алгоритмическом языке:

Алг Partition ( арг рез цел таб a [ 1: n ] )

Нач цел i , j , m , tmp

| i := 1; j := n;| m := a [ 1] | Значение основного элемента

| нц

| | нц пока m < a [ j ]

| | | j := j – 1 | Уменьшаем указатель j

| | кц

| | если i <= j

| | | то tmp := a [i]; a [i] := a [j] ; a [j] := tmp | Обмен

| | | i := i + 1

| | все

| | нц пока a [i] < m

| | | i := i + 1 | Увеличиваем указатель i

| | кц

| | если i <= j

| | | то tmp := a [i]; a [i] := a[j]; a [j] := tmp | Обмен

| | | j := j –1;

| | все

| кц при i >= j

кон

Заметим, что при использовании строгих отношений в цикле "пока" при изменении указателей j и i (вместо =) значения, равные основному элементу, действуют как барьер для обоих просмотров. Это преимущество компен­сирует такой недостаток, как "лишние" обмены элементов, равных m, которые для случайных массивов происходят в среднем крайне редко.

Теперь пора вспомнить, что наша главная цель — не разделить исходный массив, а отсортировать его. Однако от разделений до сортировки всего лишь небольшой шаг: разделив массив, можно сделать то же самое с обеими полученными частями, а затем с частями этих частей и т.д., пока каждая часть будет содержать только один элемент. Соответствующие действия можно выполнить, используя рекурсию или механизм стека. Данный метод сортировки был изобретен Ч. Хоаром. Этот метод обладает столь блестящими характеристиками (с точки зрения времени выполнения), что Хоар назвал его быстрой сортировкой.

Прежде чем представлять процедуры быстрой сортировки (приводятся вариан­ты с рекурсией), заметим, что в них используется вспомогательная процедура Partition2, работающая аналогично приведенной выше процедуре Partition, но выполняющая разделение массива на отрезке с границами (индексами) L и г. Эта процедура рекурсивно вызывает сама себя. В качестве передаваемых при рекурсивных вызовах параметров используются значения границ L и г и указателей i и j вызывающей процедуры.

^ Школьный алгоритмический язык

| Вспомогательная процедура

алг Partition2( арг цел L , г , арг рез цел таб а [1: n] )

нач цел i , j , m , tmp

| если L < r | условие продолжения рекурсивных вызовов

| | то i := L; j := r; m := a [i]

| | нц (см. выше процедуру Partition)

| | кц при i > j

| | Partition2(L , j , а) | Разделяем левую часть

| | Partition2(i , r , а) | Разделяем правую часть

| все

кон

При этом процедура сортировки оформляется очень просто:

алг Quick_Sort( арг рез цел таб а [1:n] )

нач

| Partition2( 1 , n , а )

кон

Язык Паскаль

Вспомогат. процедура, выполняющая разделение массива с границами L и r на 2 части

( см. выше )

procedure Partition2(L , r :integer; var a:arrtype);

Var i , j , m , tmp :integer;

Begin

if L < r {условие продолжения рекурсивных вызовов}

then begin

i := L; j := r; m := a [i] ;

repeat

while m
j:=j-l; {Уменьшаем указатель j }

if i <= j then

begin

tmp := a [i]; a [i] := a [j]; a [j] := tmp; {Обмен}

i := i + l

end;

while a [i] < m do

i := i + l; {Увеличиваем указатель i }

if i <= j then

begin

tmp := a [il;a [i] := a [j] ;a [j] := tmp; {Обмен }

j := j – 1;

end

until i > j;

Partition2( L , j , a ); {Разделяем левую часть}

Partition2(i,r,a); {Разделяем правую часть}

end

end

Процедура быстрой сортировки:

procedure Quick_Sort(var a:arrtype);

begin

Partition2( 1 , n , a)

end;



9521865678648173.html
9522031768654823.html
9522144837088039.html
9522202087390971.html
9522286961409500.html