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

Поразрядная сортировка для массивов

Списки довольно удобны тем, что их легко реорганизовывать, объединять и т.п. Как применить ту же идею для массивов ?

Сортировка подсчетом

Пусть у нас есть массив 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. Для этого:

    1. проинициализовать count[] нулями,

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

    3. 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 ). Аналогично случаю со списками отсортируем их в несколько проходов от младшего разряда к старшему.

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

Поразрядная сортировка беззнаковых целых чисел

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

unsigned char - 1 байт,

unsigned short int - 2 байта,

unsigned long int - 4 байта.

При этом большинство процессоров использует обратный порядок записи: от младшего байта к старшему. Так число типа short int i = 669110 = 0x1A23 непосредственно в памяти хранится так:

Если это число имеет тип long int, то под него выделяется 4 байта: long int i = 669110 = 0x00001A23.

В конце расположены ведущие нули. Таким образом, необходимо провести сортировку от начала числа к концу. Каждый байт может принимать в общем случае 256 значений: m=256.

// Создать счетчики.

// data-сортируемый массив, counters-массив для счетчиков, N-число элементов в data

template<class T>