Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Структуры и алгоритмы / Сортировка_Основные алгоритмы.doc
Скачиваний:
113
Добавлен:
23.02.2015
Размер:
679.94 Кб
Скачать
      1. Поразрядная сортировка для массивов

Одним из известных алгоритмов является метод, называемый «сортировкой подсчетом».

Пусть у нас есть массив sourceизnдесятичных цифр (m = 10). Например,source[7] = {7, 9, 8, 5, 4, 7, 7}, n=7. Здесь положимconst k=1.

  1. Создать массив countизmэлементов (счетчиков).

  2. Присвоить count[i]количество элементовsource, равныхi. Для этого:

  • проинициализовать count[]нулями;

  • пройти по sourceот начала до конца, для каждого числа увеличивая элементcountс соответствующим номером;

  • for( i=0; i<n; i++) count [ source[i] ]++;

В нашем примере count[] = { 0, 0, 0, 0, 1, 1, 0, 3, 1, 1 }.

  1. Присвоить count[i]значение, равное сумме всех элементов до данного:count[i] = count[0]+count[1]+...count[i-1].В нашем примереcount[] = { 0, 0, 0, 0, 1, 2, 2, 2, 5, 6 }.Эта сумма является количеством чисел исходного массива, меньшихi.

  2. Произвести окончательную расстановку.

Для каждого числа source[i]мы знаем, сколько определено чисел меньше него - это значение хранится вcount[ source[i] ].Таким образом, нам известно окончательное место числа в упорядоченном массиве: если естьKчисел меньше данного, то оно должно стоять на позицииK+1. Осуществляем проход по массивуsourceслева направо, одновременно заполняя выходной массивdest:

for ( i=0; i<n; i++ ) {

c = source[i];

dest[ count[c] ] = c;

count[c]++; // для повторяющихся чисел

}

Таким образом, число c=source[i]ставится на местоcount[c]. На этот случай, если числа повторяются в массиве, предусмотрен операторcount[c]++,который увеличивает значение позиции для следующего числаc, если таковое будет.

Циклы занимают (n + m)времени. Столько же требуется памяти.

Итак, мы научились за (n + m)сортировать цифры. А от цифр до строк и чисел - 1 шаг. Пусть у нас в каждом ключеkцифр (m = 10). Аналогично случаю со списками отсортируем их в несколько проходов от младшего разряда к старшему (рис. 23).

Исходная k=3 последовательность

Первый проход по 3-му разряду

Второй проход по 2-му разряду

третий проход по 1-му разряду

523

523

523

088

153

153

235

153

088

554

153

235

554

235

554

523

235

088

088

553

Offset (номер позиции)

3

2

1

Рис. 23

Общее количество операций составляет k(n+m), при используемой дополнительно памяти(n+m).Эта схема допускает небольшую оптимизацию. Заметим, что сортировка по каждому байту состоит из 2 проходов по всему массиву: на первом шаге и на четвертом. Однако можно создать сразу все массивыcount[](по одному на каждую позицию) за один проход. Неважно, как расположены числа - счетчики не меняются, поэтому это изменение корректно. Таким образом, первый шаг будет выполняться один раз за всю сортировку, а значит, общее количество проходов изменится с2kнаk+1.

      1. Эффективность поразрядной сортировки

Рост быстрой сортировки мы уже знаем: O(nlogn).Судя по оценке, поразрядная сортировка растет линейным образом поn, так какk, m- константы.

Также она растет линейным образом по k- при увеличении длины типа (количества разрядов) соответственно возрастает число проходов. Однако в последний пункт реальные условия вносят свои коррективы.

Дело в том, что основной цикл сортировки по i-му байту состоит в движении указателяuchar* bpшагамиsizeof(T)по массиву для получения очередного разряда. КогдаT=char, шаг равен1, T=short- шаг равен2,T=long- шаг равен4. Чем больше размер типа, тем менее последовательный доступ к памяти осуществляется, а это весьма существенно сказывается на скорости работы. Поэтому реальное время возрастает чуть быстрее, нежели теоретическое.

Кроме того, поразрядная сортировка уже по своей сути неинтересна для малых массивов. Каждый проход содержит минимум 256 итераций, поэтому при небольших nобщее время выполнения(n+m)определяется константойm=256.

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