Структуры и алгоритмы обработки данных


Сортировка Шелла (сортировка с уменьшающимся шагом)


В 1959 году Д. Шеллом было предложено усовершенствование сортировки с помощью метода прямого включения. Работа его представлена на рис. 6.5:

Сначала отдельно группируются и сортируются элементы, отстоящие друг от друга на расстоянии 4. Такой процесс называется четверной сортировкой. После первого прохода элементы перегруппировываются - теперь каждый элемент группы отстоит от другого на 2 позиции - и вновь сортируются. Это называется двойной сортировкой. И, наконец, на третьем проходе идет обычная или одиночная сортировка.

На первый взгляд можно засомневаться: если необходимо несколько процессов сортировки, причем в каждый включаются все элементы, то не добавят ли они больше работы, чем сэкономят? Однако, на каждом этапе либо сортируется относительно мало элементов, либо элементы уже довольно хорошо упорядочены и требуют сравнительно немного перестановок.

Ясно, что такой метод в результате дает упорядоченный массив, и, конечно, сразу же видно, что каждый проход от предыдущих только выигрывает; также очевидно, что расстояния в группах можно уменьшать по разному, лишь бы последнее было единичным, ведь в самом плохом случае последний проход и сделает всю работу.

Приводимый алгоритм основан на методе прямой вставки без барьера и не ориентирована на некую определенную последовательность расстояний, хотя в нем для конкретности заданы шаги 5, 3 и 1.

При использовании метода барьера  каждая из сортировок нуждается в постановке своего собственного барьера, и программу для определения его местонахождения необходимо делать насколько возможно простой. Поэтому приходится расширять массив до [-h1..N].

h[1..t] - массив размеров  шагов

a[1..n] - сортируемый массив

k - шаг сортировки

x - значение вставляемого элемента



Subroutine  ShellSort

 

Псевдокод:

const t = 3

          h(1) = 5

          h(2) = 3

          h(3) = 1

  for m = 1 to t

    k = h(m)

    for i = k + 1 to n

      x = a(i)

      for j = i - k to 1 step -k

        if  x < a(j) then

          a( j+k) = a(j)

        else

           goto L

         endif

       next j

  L:  a(j+k) = x

      next i

     next m

    return

Паскаль:

const   t = 3;

            h(1) = 5;

            h(2) = 3;

            h(3) = 1;

var

  h: array [1..t] of integer;

  a: array [1..n] of integer;

   k, x, m, t, i, j: integer;

 begin

   for  m = 1 to t do

     begin

       k:= h(m);

       for i = k + 1 to n do

         begin

          x:= a(i);           

          for j = i-k  downto k   do

             begin

              if  x < a(j ) then

                a(j+k):= a(j);

               else

                 goto 1;

              end ;

             end;

            end;

1:          a(j+1) = x ;

         end;   

    end .

<
Не доказано, какие расстояния дают наилучший результат, но они не должны быть множителями один другого.

Д. Кнут предлагает такую последовательность шагов (в обратном порядке): 1, 3, 7, 15, 31, … То есть:  h m-1 = h m + 1,

t = log2n - 1. При такой организации алгоритма его эффективность имеет порядок O ( n1.2)

Контрольные вопросы

        1.        Что такое сортировка?

        2.        Назовите основные методы сортировки.

        3.        Какие методы сортировки относятся к строгим?

        4.        Какие методы сортировки относятся к улучшенным?

        5.        Какая сортировка называется устойчивой?

        6.        В чем состоит суть метода прямого включения?

        7.        В чем состоит суть метода прямого выбора?

        8.        В чем состоит суть метода прямого обмена?

        9.        Назовите разницу между этими тремя методами.

     10.     Какой метод сортировки является самым эффективным?

     11.     К какому из основных методов относится метод Шелла?


Содержание раздела