<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=5.18.215.129&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=5.18.215.129&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/5.18.215.129"/>
		<updated>2026-05-10T14:03:28Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BF%D0%BE%D0%B4%D1%81%D1%87%D1%91%D1%82%D0%BE%D0%BC&amp;diff=66029</id>
		<title>Сортировка подсчётом</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%BF%D0%BE%D0%B4%D1%81%D1%87%D1%91%D1%82%D0%BE%D0%BC&amp;diff=66029"/>
				<updated>2018-06-15T12:19:17Z</updated>
		
		<summary type="html">&lt;p&gt;5.18.215.129: /* Псевдокод */ C[j] изменил на C[number]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка подсчётом''' (англ. ''counting sort'') {{---}} алгоритм сортировки целых чисел в диапазоне от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до некоторой константы &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; или сложных объектов, работающий за линейное время.&lt;br /&gt;
== Сортировка целых чисел ==&lt;br /&gt;
Это простейший вариант алгоритма.&lt;br /&gt;
=== Описание ===&lt;br /&gt;
Исходная последовательность чисел длины &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, а в конце отсортированная, хранится в массиве &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Также используется вспомогательный массив &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; с индексами от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;\mathrm k - 1&amp;lt;/tex&amp;gt;, изначально заполняемый нулями.&lt;br /&gt;
&lt;br /&gt;
* Последовательно пройдём по массиву &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и запишем в &amp;lt;tex&amp;gt;C[i]&amp;lt;/tex&amp;gt; количество чисел, равных &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Теперь достаточно пройти по массиву &amp;lt;tex&amp;gt;C&amp;lt;/tex&amp;gt; и для каждого &amp;lt;tex&amp;gt;number \in \{0, ..., \mathrm k - 1\}&amp;lt;/tex&amp;gt; в массив &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; последовательно записать число &amp;lt;tex&amp;gt;number\&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt; C[number]&amp;lt;/tex&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''function''' simpleCountingSort(A: '''int[n]'''): &lt;br /&gt;
     '''for''' number = 0 '''to''' k - 1&lt;br /&gt;
         C[number] = 0 &lt;br /&gt;
     '''for''' i = 0 '''to''' n - 1&lt;br /&gt;
         C[A[i]] = C[A[i]] + 1;     &lt;br /&gt;
     pos = 0;&lt;br /&gt;
     '''for''' number = 0 '''to''' k - 1&lt;br /&gt;
         '''for''' i = 0 '''to''' C[number] - 1&lt;br /&gt;
             A[pos] = number;&lt;br /&gt;
             pos = pos + 1;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Сортировка сложных объектов ==&lt;br /&gt;
Сортировка целых чисел за линейное время это хорошо, но недостаточно. Иногда бывает очень желательно применить быстрый алгоритм [[#Сортировка целых чисел|сортировки подсчетом]] для упорядочивания набора каких-либо &amp;quot;сложных&amp;quot; данных. Под &amp;quot;сложными объектами&amp;quot; здесь подразумеваются структуры, содержащие в себе несколько полей. Одно из них мы выделим и назовем ключом, сортировка будет идти именно по нему (предполагается, что значения, принимаемые ключом {{---}} целые числа в диапазоне от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;\mathrm k-1&amp;lt;/tex&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Мы не сможем использовать здесь в точности тот же алгоритм, что и для сортировки подсчетом обычных целых чисел, потому что в наборе могут быть различные структуры, имеющие одинаковые ключи. Существует два способа справиться с этой проблемой {{---}} использовать списки для хранения структур в отсортированном массиве или заранее посчитать количество структур с одинаковыми ключами для каждого значения ключа.  &lt;br /&gt;
&lt;br /&gt;
=== Описание ===&lt;br /&gt;
Исходная последовательность из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; структур хранится в массиве &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, а отсортированная {{---}} в массиве &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; того же размера. Кроме того, используется вспомогательный массив &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; с индексами от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;\mathrm k-1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Идея алгоритма состоит в предварительном подсчете количества элементов с различными ключами в исходном массиве и разделении результирующего массива на части соответствующей длины (будем называть их блоками). Затем при повторном проходе исходного массива каждый его элемент копируется в специально отведенный его ключу блок, в первую свободную ячейку. Это осуществляется с помощью массива индексов &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, в котором хранятся индексы начала блоков для различных ключей. &amp;lt;tex&amp;gt;P[key]&amp;lt;/tex&amp;gt; {{---}} индекс в результирующем массиве, соответствующий первому элементу блока для ключа &amp;lt;tex&amp;gt;key&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
* Пройдем по исходному массиву &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и запишем в &amp;lt;tex&amp;gt;P[i]&amp;lt;/tex&amp;gt; количество структур, ключ которых равен &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. &lt;br /&gt;
[[Файл:Building_P.png]]&lt;br /&gt;
&lt;br /&gt;
* Мысленно разобьем массив &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; блоков, длина каждого из которых равна соответственно &amp;lt;tex&amp;gt;P[0]&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;P[1]&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;P[k]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
[[Файл:Splitting_B_w_colors.png]]&lt;br /&gt;
&lt;br /&gt;
* Теперь массив &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; нам больше не нужен. Превратим его в массив, хранящий в &amp;lt;tex&amp;gt;P[i]&amp;lt;/tex&amp;gt; сумму элементов от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;i-1&amp;lt;/tex&amp;gt; старого массива &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. &lt;br /&gt;
[[Файл:P_after_adding.png]]&lt;br /&gt;
&lt;br /&gt;
* Теперь &amp;quot;сдвинем&amp;quot; массив &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; на элемент вперед: в новом массиве &amp;lt;tex&amp;gt;P[0] = 0&amp;lt;/tex&amp;gt;, а для &amp;lt;tex&amp;gt;i &amp;gt; 0&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;P[i] = P_{old}[i-1]&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;P_{old}&amp;lt;/tex&amp;gt; {{---}} старый массив &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;. &amp;lt;br&amp;gt; Это можно сделать за один проход по массиву &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt;, причем одновременно с предыдущим шагом. &amp;lt;br&amp;gt; После этого действия в массиве &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; будут хранится индексы массива &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;P[key]&amp;lt;/tex&amp;gt; указывает на начало блока в &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt;, соответствующего ключу &amp;lt;tex&amp;gt;key&amp;lt;/tex&amp;gt;.&lt;br /&gt;
[[Файл:P_as_array_of_pointers.png]]&lt;br /&gt;
&lt;br /&gt;
* Произведем саму сортировку. Еще раз пройдем по исходному массиву &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;i \in [0, n-1]&amp;lt;/tex&amp;gt; будем помещать структуру &amp;lt;tex&amp;gt;A[i]&amp;lt;/tex&amp;gt; в массив &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; на место &amp;lt;tex&amp;gt;P[A[i].key]&amp;lt;/tex&amp;gt;, а затем увеличивать &amp;lt;tex&amp;gt;P[A[i].key]&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;. Здесь &amp;lt;tex&amp;gt;A[i].key&amp;lt;/tex&amp;gt; {{---}} это ключ структуры, находящейся в массиве &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-том месте. &lt;br /&gt;
[[Файл:Sorting_A.png]]&lt;br /&gt;
&lt;br /&gt;
Таким образом после завершения алгоритма в &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; будет содержаться исходная последовательность в отсортированном виде (так как блоки расположены по возрастанию соответствующих ключей).&lt;br /&gt;
&lt;br /&gt;
Стоит также отметить, что эта сортировка является устойчивой, так как два элемента с одинаковыми ключами будут добавлены в том же порядке, в каком просматривались в исходном массиве &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Благодаря этому свойству существует [[цифровая сортировка]].&lt;br /&gt;
&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
Здесь &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; {{---}} массивы структур размера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, с индексами от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;n-1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; {{---}} целочисленный массив размера &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;, с индексами от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k-1&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; {{---}} количество различных ключей.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''function''' complexCountingSort(A: '''int[n]''', B: '''int[n]'''):&lt;br /&gt;
     '''for''' i = 0 '''to''' k - 1&lt;br /&gt;
         P[i] = 0;         &lt;br /&gt;
     '''for''' i = 0 '''to''' length[A] - 1&lt;br /&gt;
         P[A[i].key] = P[A[i].key] + 1;     &lt;br /&gt;
     carry = 0;&lt;br /&gt;
     '''for''' i = 0 '''to''' k - 1&lt;br /&gt;
         temporary = P[i];&lt;br /&gt;
         P[i] = carry;&lt;br /&gt;
         carry = carry + temporary;     &lt;br /&gt;
     '''for''' i = 0 '''to''' length[A] - 1&lt;br /&gt;
         B[P[A[i].key]] = A[i];&lt;br /&gt;
         P[A[i].key] = P[A[i].key] + 1;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Здесь шаги 3 и 4 из описания объединены в один цикл.&lt;br /&gt;
Обратите внимание, что в последнем цикле инструкцией&lt;br /&gt;
 B[P[A[i].key]] = A[i];&lt;br /&gt;
копируется структура &amp;lt;tex&amp;gt;A[i]&amp;lt;/tex&amp;gt; целиком, а не только её ключ.&lt;br /&gt;
&lt;br /&gt;
== Анализ ==&lt;br /&gt;
В первом алгоритме первые два цикла работают за &amp;lt;tex&amp;gt;\Theta(k)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;\Theta(n)&amp;lt;/tex&amp;gt;, соответственно; двойной цикл за &amp;lt;tex&amp;gt;\Theta(n + k)&amp;lt;/tex&amp;gt;. Алгоритм имеет линейную временную трудоёмкость &amp;lt;tex&amp;gt;\Theta(n + k)&amp;lt;/tex&amp;gt;. Используемая дополнительная память равна &amp;lt;tex&amp;gt;\Theta(k)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Второй алгоритм состоит из двух проходов по массиву &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt; размера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; и одного прохода по массиву &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; размера &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Его трудоемкость, таким образом, равна &amp;lt;tex&amp;gt;\Theta(n + k)&amp;lt;/tex&amp;gt;. На практике сортировку подсчетом имеет смысл применять, если &amp;lt;tex&amp;gt;k = O(n)&amp;lt;/tex&amp;gt;, поэтому можно считать время работы алгоритма равным &amp;lt;tex&amp;gt;\Theta(n)&amp;lt;/tex&amp;gt;. &amp;lt;br&amp;gt;&lt;br /&gt;
Как и в обычной сортировке подсчетом, требуется &amp;lt;tex&amp;gt;\Theta(n + k)&amp;lt;/tex&amp;gt; дополнительной памяти {{---}} на хранение массива &amp;lt;tex&amp;gt;B&amp;lt;/tex&amp;gt; размера &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; и массива &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; размера &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм работает за линейное время, но является псевдополиномиальным.&lt;br /&gt;
&lt;br /&gt;
== Поиск диапазона ключей ==&lt;br /&gt;
Если диапазон значений не известен заранее, то его можно найти с помощью линейного поиска минимума и максимума в исходном массиве, что не повлияет на асимптотику алгоритма. &amp;lt;br&amp;gt;&lt;br /&gt;
Нужно учитывать, что минимум может быть отрицательным, в то время как в массиве &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; индексы от &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k-1&amp;lt;/tex&amp;gt;. Поэтому при работе с массивом &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; из исходного &amp;lt;tex&amp;gt;A[i]&amp;lt;/tex&amp;gt;  необходимо вычитать минимум, а при обратной записи в &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; прибавлять его.&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/Сортировка_подсчётом Сортировка подсчетом {{---}} Википедия]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Counting_sort Counting sort {{---}} Wikipedia]&lt;br /&gt;
* Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. — 2-е изд. — М.: Издательский дом «Вильямс», 2007. — С. 224{{---}}226.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Сортировки]]&lt;br /&gt;
[[Категория: Другие сортировки]]&lt;/div&gt;</summary>
		<author><name>5.18.215.129</name></author>	</entry>

	</feed>