Изменения

Перейти к: навигация, поиск

Сортировка подсчетом сложных объектов

1091 байт добавлено, 23:33, 15 мая 2012
Переписал текст, удалил старую картинку, добавил новый раздел и новую картинку.
Иногда бывает очень желательно применить быстрый алгоритм [[Сортировка подсчетом|сортировки подсчетом]] для упорядочивания набора каких-либо "сложных" данных. Под "сложными объектами" здесь подразумеваются структуры, содержащие в себе несколько полей. Одно из них мы выделим и назовем ключом, сортировка будет идти именно по нему (предполагается, что значения, принимаемые ключом - целые числа в диапазоне от <tex>0</tex> до <tex>k-1</tex>).
Мы не сможем использовать здесь в точности тот же алгоритм, что и для сортировки подсчетом обычных целых чисел, потому что в наборе могут быть различные структуры, имеющие одинаковые ключи.Существует два способа справиться с этой проблемой {{---}} использовать списки для хранения структур в отсортированном массиве или заранее посчитать количество структур с одинаковыми ключами для каждого значения ключа.
== Решение Использование списков ==Пусть далее исходная последовательность из <tex>n</tex> структур хранится в массиве <tex>A</tex>, а отсортированная - в массиве <tex>BP</tex>, причем ее ключи принадлежат множеству с индексами от <tex>0..</tex> до <tex>k-1</tex>.
В качестве модификации можно сделать Сделаем из каждой ячейки массива А <tex>B</tex> список, в который будем добавлять структуры с одинаковыми ключами. Однако, этот вариант плох тем, что надо поддерживать сам список, что не является самым простым решением. К тому же нам надо будет хранить дополнительную информацию в виде ссылок на следующий элемент в списке.
Избавиться от этих недостатков можно следующим образом[[Файл:List_solution.png|500px|]]
[[Файл:massAЭтот вариант плох тем, что надо поддерживать сам список, что не является самым простым решением. Еще придется хранить дополнительную информацию в виде ссылок на следующий элемент в списке. И кроме того, такое представление отсортированного массива неудобно в использовании.Избавиться от этих недостатков можно используя другую модификацию алгоритма сортировки подсчетом.png|800px|]]
* Подсчитаем количество разных == Подсчет числа различных ключей ==Здесь исходная последовательность из <tex>n</tex> структур хранится в списке (пусть их будет k)массиве <tex>A</tex>, а также количество ключей каждого видаотсортированная - в массиве <tex>B</tex> того же размера. Пусть Кроме того используется вспомогательный массив Р[i] содержит количество ключей, равных i. Очевидно, что это делается за О(n).* Разобьем массив А на k блоков, длина каждого из которых равна соотв. <tex>P[1], P[2], ..., P[k], и поставим над первым элементом каждого блока по указателю point_i, который в дальнейшем будет указывать на первый свободный элемент в своем блоке i.* Теперь массив Р нам больше не нужен. Тогда превратим его в массив, хранящий в Р[i] - сумму элементов </tex> с индексами от <tex>0 </tex> до i - 1 старого массива Р. Это делается за один пробег по массиву.* Теперь собственно сортировка. Для определения на очередном шаге по массиву С, куда вставить текущий элемент посмотрим на поле key и запишем эту структурку в <tex>A[P[key] + point_{key}]k-1</tex>. Затем увеличим соотв. значение указателя на 1. Таким образом после завершения алгоритма в А будет содержаться наша последовательность в отсортированном виде (так как блоки расположены по возрастанию соотв. ключей).
* Пройдем по исходному массиву <tex>A</tex> и запишем в <tex>P[i]</tex> количество структур, ключ которых равен <tex>i</tex>. Это можно сделать за <tex> O(n)</tex>.* Условно разобьем массив <tex>B</tex> на <tex>k</tex> блоков, длина каждого из которых равна соответственно <tex>P[1]</tex>, <tex>P[2]</tex>, ..., <tex>P[k]</tex>.* Теперь массив <tex>P</tex> нам больше не нужен. Превратим его в массив, хранящий в <tex>P[i]</tex> сумму элементов от <tex>0</tex> до <tex>i-1</tex> старого массива <tex>P</tex>. Это делается за один пробег по массиву <tex>P</tex>, то есть имеет сложность <tex> O(k)</tex>.* Произведем саму сортировку. Еще раз пройдем по исходному массиву <tex>A</tex> и для всех <tex>i \in [0, n-1]</tex> будем помещать структуру <tex>A[i]</tex> в массив <tex>B</tex> на место <tex>P[A[i].key]-1</tex>. Здесь <tex>A[i].key</tex> {{---}} это ключ структуры, находящейся в массиве <tex>A</tex> на <tex>i</tex>-том месте. Затем увеличим <tex>P[A[i].key]</tex> на единицу.  Таким образом после завершения алгоритма в <tex>B</tex> будет содержаться исходная последовательность в отсортированном виде (так как блоки расположены по возрастанию соответствующих ключей). Стоит также отметить, что эта сортировка устойчиваяявляется устойчивой, так как два элемента с одинаковыми ключами будут добавлены в том же порядке, в котором каком просматривались в изначальном исходном массиве<tex>A</tex>.
==Источники==
101
правка

Навигация