<?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=Da1s60</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=Da1s60"/>
		<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/Da1s60"/>
		<updated>2026-06-11T16:46:36Z</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25343</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25343"/>
				<updated>2012-06-12T16:45:32Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;0&amp;lt; e &amp;lt; 1&amp;lt;/tex&amp;gt;) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хеширование для всех чисел хранимых в контейнере. Для этого используется хеш функция для хеширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хеш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хеш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством &amp;lt;tex&amp;gt;\{0, \ldots, 2^b - 1\}&amp;lt;tex&amp;gt;, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хеш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захеширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хеш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хеш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Такая хеш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хеширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хеширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хешированных значений для каждого числа. После сортировки на хешированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = &amp;lt;tex&amp;gt;\{1, 4, 6, 8, 9, 13, 14\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&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;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&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;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&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;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&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;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При таком помещении сразу возникает следующая проблемой.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&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;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
# Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, \ldots, m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, \ldots, S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, \ldots, T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, \ldots, b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хешированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хеш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хеш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хеш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Хеш функция, которая используется, находится следующим образом. Будут хешироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хеш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хеш функций.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хешированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хешированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хеш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хешированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хешированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хешированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2} \ldots t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хешированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}0^{j}t_{1, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2,  \ldots, h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}t_{1, 2}t_{2, 2} \ldots t_{1, h/ \log\log n}t_{2, h/ \log\log n} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хеш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} \ldots t_{k, h/ \log\log n} k = 1, 2, \ldots, \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} \ldots t_{1, h/ \log\log n}0^{r}t_{2, 1} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} \ldots t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
# Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
# А. Андерссон. Fast deterministic sorting and searching in linear space. Proc. 1996 IEEE Symp. on Foundations of Computer Science. 135-141(1996)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25342</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25342"/>
				<updated>2012-06-12T16:44:47Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;0&amp;lt; e &amp;lt; 1&amp;lt;/tex&amp;gt;) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хеширование для всех чисел хранимых в контейнере. Для этого используется хеш функция для хеширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хеш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хеш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) \div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством &amp;lt;tex&amp;gt;\{0, \ldots, 2^b - 1\}&amp;lt;tex&amp;gt;, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хеш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захеширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хеш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хеш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Такая хеш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хеширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хеширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хешированных значений для каждого числа. После сортировки на хешированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = &amp;lt;tex&amp;gt;\{1, 4, 6, 8, 9, 13, 14\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&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;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&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;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&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;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&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;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При таком помещении сразу возникает следующая проблемой.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&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;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
# Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, \ldots, m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, \ldots, S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, \ldots, T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, \ldots, b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хешированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хеш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хеш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хеш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Хеш функция, которая используется, находится следующим образом. Будут хешироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хеш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хеш функций.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хешированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хешированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хеш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хешированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хешированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хешированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2} \ldots t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хешированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}0^{j}t_{1, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2,  \ldots, h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}t_{1, 2}t_{2, 2} \ldots t_{1, h/ \log\log n}t_{2, h/ \log\log n} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хеш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} \ldots t_{k, h/ \log\log n} k = 1, 2, \ldots, \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} \ldots t_{1, h/ \log\log n}0^{r}t_{2, 1} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} \ldots t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
# Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
# А. Андерссон. Fast deterministic sorting and searching in linear space. Proc. 1996 IEEE Symp. on Foundations of Computer Science. 135-141(1996)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25341</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25341"/>
				<updated>2012-06-12T16:43:29Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;0&amp;lt; e &amp;lt; 1&amp;lt;/tex&amp;gt;) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хеширование для всех чисел хранимых в контейнере. Для этого используется хеш функция для хеширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хеш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хеш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством &amp;lt;tex&amp;gt;\{0, \ldots, 2^b - 1\}&amp;lt;tex&amp;gt;, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хеш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захеширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хеш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хеш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Такая хеш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хеширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хеширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хешированных значений для каждого числа. После сортировки на хешированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = &amp;lt;tex&amp;gt;\{1, 4, 6, 8, 9, 13, 14\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&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;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&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;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&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;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&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;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При таком помещении сразу возникает следующая проблемой.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&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;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
# Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, \ldots, m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, \ldots, S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, \ldots, T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, \ldots, b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хешированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хеш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хеш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хеш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Хеш функция, которая используется, находится следующим образом. Будут хешироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хеш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хеш функций.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хешированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хешированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хеш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хешированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хешированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хешированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2} \ldots t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хешированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}0^{j}t_{1, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2,  \ldots, h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}t_{1, 2}t_{2, 2} \ldots t_{1, h/ \log\log n}t_{2, h/ \log\log n} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хеш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} \ldots t_{k, h/ \log\log n} k = 1, 2, \ldots, \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} \ldots t_{1, h/ \log\log n}0^{r}t_{2, 1} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} \ldots t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
# Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
# А. Андерссон. Fast deterministic sorting and searching in linear space. Proc. 1996 IEEE Symp. on Foundations of Computer Science. 135-141(1996)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25292</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25292"/>
				<updated>2012-06-12T14:08:24Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;0&amp;lt; e &amp;lt; 1&amp;lt;/tex&amp;gt;) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством &amp;lt;tex&amp;gt;\{0, \ldots, 2^b - 1\}&amp;lt;tex&amp;gt;, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = &amp;lt;tex&amp;gt;\{1, 4, 6, 8, 9, 13, 14\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&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;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&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;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&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;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&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;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При таком помещении сразу возникает следующая проблемой.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&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;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
# Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, \ldots, m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, \ldots, S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, \ldots, T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, \ldots, b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которая используется, находится следующим образом. Будут хэшироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хэшированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хэш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2} \ldots t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}0^{j}t_{1, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2,  \ldots, h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}t_{1, 2}t_{2, 2} \ldots t_{1, h/ \log\log n}t_{2, h/ \log\log n} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} \ldots t_{k, h/ \log\log n} k = 1, 2, \ldots, \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} \ldots t_{1, h/ \log\log n}0^{r}t_{2, 1} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} \ldots t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
# Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
# А. Андерссон. Fast deterministic sorting and searching in linear space. Proc. 1996 IEEE Symp. on Foundations of Computer Science. 135-141(1996)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25291</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25291"/>
				<updated>2012-06-12T14:07:56Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;0&amp;lt; e &amp;lt; 1&amp;lt;/tex&amp;gt;) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^{b}) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством &amp;lt;tex&amp;gt;\{0, \ldots, 2^b - 1\}&amp;lt;tex&amp;gt;, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = &amp;lt;tex&amp;gt;\{1, 4, 6, 8, 9, 13, 14\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&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;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&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;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&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;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&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;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При таком помещении сразу возникает следующая проблемой.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&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;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
# Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, \ldots, m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, \ldots, S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, \ldots, T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, \ldots, b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которая используется, находится следующим образом. Будут хэшироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хэшированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хэш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2} \ldots t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}0^{j}t_{1, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2,  \ldots, h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}t_{1, 2}t_{2, 2} \ldots t_{1, h/ \log\log n}t_{2, h/ \log\log n} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} \ldots t_{k, h/ \log\log n} k = 1, 2, \ldots, \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} \ldots t_{1, h/ \log\log n}0^{r}t_{2, 1} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} \ldots t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
# Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
# А. Андерссон. Fast deterministic sorting and searching in linear space. Proc. 1996 IEEE Symp. on Foundations of Computer Science. 135-141(1996)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25290</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25290"/>
				<updated>2012-06-12T14:06:16Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (&amp;lt;tex&amp;gt;0&amp;lt; e &amp;lt; 1&amp;lt;/tex&amp;gt;) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством &amp;lt;tex&amp;gt;\{0, \ldots, 2^b - 1\}&amp;lt;tex&amp;gt;, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = &amp;lt;tex&amp;gt;\{1, 4, 6, 8, 9, 13, 14\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&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;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&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;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&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;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&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;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При таком помещении сразу возникает следующая проблемой.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&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;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
# Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, \ldots, m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, \ldots, S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, \ldots, T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, \ldots, b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которая используется, находится следующим образом. Будут хэшироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хэшированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хэш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2} \ldots t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}0^{j}t_{1, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2,  \ldots, h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}t_{1, 2}t_{2, 2} \ldots t_{1, h/ \log\log n}t_{2, h/ \log\log n} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} \ldots t_{k, h/ \log\log n} k = 1, 2, \ldots, \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} \ldots t_{1, h/ \log\log n}0^{r}t_{2, 1} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} \ldots t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
# Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
# А. Андерссон. Fast deterministic sorting and searching in linear space. Proc. 1996 IEEE Symp. on Foundations of Computer Science. 135-141(1996)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A5%D0%B0%D0%BD%D0%B0&amp;diff=25289</id>
		<title>Обсуждение:Сортировка Хана</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A5%D0%B0%D0%BD%D0%B0&amp;diff=25289"/>
				<updated>2012-06-12T14:05:25Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* &amp;lt;tex&amp;gt;log&amp;lt;/tex&amp;gt; -&amp;gt; &amp;lt;tex&amp;gt;\log&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Сокращение Э.П.дерево выглядит очень странно, лучше ЭП-дерево&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Если есть ещё какая-нибудь информация про это самое ЭП-дерево, добавить в ссылки&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Раздел &amp;quot;необходимая информация&amp;quot; лучше переименовать в &amp;quot;определения&amp;quot;, и вместо блоков с определениями сделать обычный список&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Определение контейнера какое-то странное, и ещё вместо __int32 и __int64 писать &amp;quot;32-битные числа&amp;quot; и &amp;quot;64-битные числа&amp;quot;&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Если мы&amp;quot;, &amp;quot;тогда мы&amp;quot; выглядит плохо. Лучше всего — писать обезличенно.&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
постарался убрать все &amp;quot;Если мы&amp;quot;, &amp;quot;тогда мы&amp;quot;, надеюсь вышло более-менее обезличенно&lt;br /&gt;
&lt;br /&gt;
* Посмотреть на четвёртое определение: я там дописал, как в техе записывать всякие минимумы, принадлежность множеству и т.д. Использовать такие формулы вместо текстовых описаний.&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
сделал где увидел&lt;br /&gt;
&lt;br /&gt;
* Вместо &amp;gt;= писать &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; (соответственно &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; вместо &amp;lt;=)&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Очень крупные абзацы в тексте, разбить на абзацы по-мельче&lt;br /&gt;
&lt;br /&gt;
на мой взгляд, в каждом абзаце представлена законченная мысль, поэтому не думаю, что их надо разделять&lt;br /&gt;
&lt;br /&gt;
для удобства я их разделил пустой строкой (чтобы не сливались в сплошной текст)&lt;br /&gt;
&lt;br /&gt;
* Вместо ручной нумерации использовать вики-разметку&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
сделал где, по моему мнению, нужна была нумерация&lt;br /&gt;
&lt;br /&gt;
* Корень из n писать как &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
сделал везде, кроме одного заголовка, никак не получается выводить его как ссылку если писать через корешок&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Вывод&amp;quot; снести, он не нужен.&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
--[[Участник:Андрей Шулаев|Андрей Шулаев]] 14:05, 12 июня 2012 (GST)&lt;br /&gt;
&lt;br /&gt;
Рекомендую кураторам обратить внимание на то, что в статье полно формул, записанных вот так: {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} вместо &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
готово&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25288</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25288"/>
				<updated>2012-06-12T14:04:48Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством &amp;lt;tex&amp;gt;\{0, \ldots, 2^b - 1\}&amp;lt;tex&amp;gt;, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = &amp;lt;tex&amp;gt;\{1, 4, 6, 8, 9, 13, 14\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&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;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&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;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&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;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&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;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При таком помещении сразу возникает следующая проблемой.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&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;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
# Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, \ldots, m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, \ldots, S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, \ldots, T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, \ldots, b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которая используется, находится следующим образом. Будут хэшироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хэшированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хэш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2} \ldots t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}0^{j}t_{1, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2,  \ldots, h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}t_{1, 2}t_{2, 2} \ldots t_{1, h/ \log\log n}t_{2, h/ \log\log n} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} \ldots t_{k, h/ \log\log n} k = 1, 2, \ldots, \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} \ldots t_{1, h/ \log\log n}0^{r}t_{2, 1} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} \ldots t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
# Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
# А. Андерссон. Fast deterministic sorting and searching in linear space. Proc. 1996 IEEE Symp. on Foundations of Computer Science. 135-141(1996)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25286</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25286"/>
				<updated>2012-06-12T14:03:50Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством &amp;lt;tex&amp;gt;\{0, \ldots, 2^b - 1\}&amp;lt;tex&amp;gt;, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, .\ldots, &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = &amp;lt;tex&amp;gt;\{1, 4, 6, 8, 9, 13, 14\}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&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;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&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;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&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;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&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;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При таком помещении сразу возникает следующая проблемой.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&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;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
# Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, \ldots, a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, \ldots, m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, \ldots, S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, \ldots, T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, \ldots, a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, \ldots, b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, \ldots, S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которая используется, находится следующим образом. Будут хэшироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хэшированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хэш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;\ldots&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2} \ldots t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}0^{j}t_{1, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2,  \ldots, h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} \ldots t_{\log\log n, 1}t_{1, 2}t_{2, 2} \ldots t_{1, h/ \log\log n}t_{2, h/ \log\log n} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} \ldots t_{k, h/ \log\log n} k = 1, 2, \ldots, \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} \ldots t_{1, h/ \log\log n}0^{r}t_{2, 1} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} \ldots t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} \ldots t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
# Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
# А. Андерссон. Fast deterministic sorting and searching in linear space. Proc. 1996 IEEE Symp. on Foundations of Computer Science. 135-141(1996)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25285</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25285"/>
				<updated>2012-06-12T13:55:34Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества &amp;lt;tex&amp;gt;{0, 1, ..., m - 1}&amp;lt;/tex&amp;gt; с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством &amp;lt;tex&amp;gt;{0, ..., 2^b - 1}&amp;lt;tex&amp;gt;, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&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;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&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;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&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;{0, 1, ..., m - 1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&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;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При таком помещении сразу возникает следующая проблемой.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&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;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
# Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которая используется, находится следующим образом. Будут хэшироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хэшированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хэш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
# Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
# А. Андерссон. Fast deterministic sorting and searching in linear space. Proc. 1996 IEEE Symp. on Foundations of Computer Science. 135-141(1996)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25269</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25269"/>
				<updated>2012-06-12T13:17:46Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&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;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&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;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&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; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&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;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При таком помещении сразу возникает следующая проблемой.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&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;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
# Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которая используется, находится следующим образом. Будут хэшироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хэшированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хэш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
# Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
# А. Андерссон. Fast deterministic sorting and searching in linear space. Proc. 1996 IEEE Symp. on Foundations of Computer Science. 135-141(1996)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A5%D0%B0%D0%BD%D0%B0&amp;diff=25265</id>
		<title>Обсуждение:Сортировка Хана</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A5%D0%B0%D0%BD%D0%B0&amp;diff=25265"/>
				<updated>2012-06-12T13:12:01Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* &amp;lt;tex&amp;gt;log&amp;lt;/tex&amp;gt; -&amp;gt; &amp;lt;tex&amp;gt;\log&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Сокращение Э.П.дерево выглядит очень странно, лучше ЭП-дерево&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Если есть ещё какая-нибудь информация про это самое ЭП-дерево, добавить в ссылки&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Раздел &amp;quot;необходимая информация&amp;quot; лучше переименовать в &amp;quot;определения&amp;quot;, и вместо блоков с определениями сделать обычный список&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Определение контейнера какое-то странное, и ещё вместо __int32 и __int64 писать &amp;quot;32-битные числа&amp;quot; и &amp;quot;64-битные числа&amp;quot;&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Если мы&amp;quot;, &amp;quot;тогда мы&amp;quot; выглядит плохо. Лучше всего — писать обезличенно.&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
постарался убрать все &amp;quot;Если мы&amp;quot;, &amp;quot;тогда мы&amp;quot;, надеюсь вышло более-менее обезличенно&lt;br /&gt;
&lt;br /&gt;
* Посмотреть на четвёртое определение: я там дописал, как в техе записывать всякие минимумы, принадлежность множеству и т.д. Использовать такие формулы вместо текстовых описаний.&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
сделал где увидел&lt;br /&gt;
&lt;br /&gt;
* Вместо &amp;gt;= писать &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; (соответственно &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; вместо &amp;lt;=)&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Очень крупные абзацы в тексте, разбить на абзацы по-мельче&lt;br /&gt;
&lt;br /&gt;
на мой взгляд, в каждом абзаце представлена законченная мысль, поэтому не думаю, что их надо разделять&lt;br /&gt;
&lt;br /&gt;
для удобства я их разделил пустой строкой (чтобы не сливались в сплошной текст)&lt;br /&gt;
&lt;br /&gt;
* Вместо ручной нумерации использовать вики-разметку&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
сделал где, по моему мнению, нужна была нумерация&lt;br /&gt;
&lt;br /&gt;
* Корень из n писать как &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
сделал везде, кроме одного заголовка, никак не получается выводить его как ссылку если писать через корешок&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Вывод&amp;quot; снести, он не нужен.&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
--[[Участник:Андрей Шулаев|Андрей Шулаев]] 14:05, 12 июня 2012 (GST)&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A5%D0%B0%D0%BD%D0%B0&amp;diff=25264</id>
		<title>Обсуждение:Сортировка Хана</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A5%D0%B0%D0%BD%D0%B0&amp;diff=25264"/>
				<updated>2012-06-12T13:10:53Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* &amp;lt;tex&amp;gt;log&amp;lt;/tex&amp;gt; -&amp;gt; &amp;lt;tex&amp;gt;\log&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Сокращение Э.П.дерево выглядит очень странно, лучше ЭП-дерево&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Если есть ещё какая-нибудь информация про это самое ЭП-дерево, добавить в ссылки&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Раздел &amp;quot;необходимая информация&amp;quot; лучше переименовать в &amp;quot;определения&amp;quot;, и вместо блоков с определениями сделать обычный список&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Определение контейнера какое-то странное, и ещё вместо __int32 и __int64 писать &amp;quot;32-битные числа&amp;quot; и &amp;quot;64-битные числа&amp;quot;&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Если мы&amp;quot;, &amp;quot;тогда мы&amp;quot; выглядит плохо. Лучше всего — писать обезличенно.&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
постарался убрать все &amp;quot;Если мы&amp;quot;, &amp;quot;тогда мы&amp;quot;, надеюсь вышло более-менее обезличенно&lt;br /&gt;
&lt;br /&gt;
* Посмотреть на четвёртое определение: я там дописал, как в техе записывать всякие минимумы, принадлежность множеству и т.д. Использовать такие формулы вместо текстовых описаний.&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
сделал где увидел&lt;br /&gt;
&lt;br /&gt;
* Вместо &amp;gt;= писать &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; (соответственно &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; вместо &amp;lt;=)&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Очень крупные абзацы в тексте, разбить на абзацы по-мельче&lt;br /&gt;
&lt;br /&gt;
на мой взгляд, в каждом абзаце представлена законченная мысль, поэтому не думаю, что их надо разделять&lt;br /&gt;
&lt;br /&gt;
для удобства я их разделил пустой строкой (чтобы не сливались в сплошной текст)&lt;br /&gt;
&lt;br /&gt;
* Вместо ручной нумерации использовать вики-разметку&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
сделал где, по моему мнению, нужна была нумерация&lt;br /&gt;
&lt;br /&gt;
* Корень из n писать как &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
сделал везде, кроме одного заголовка, никак не получается выводить его как ссылку если писать как &amp;lt;tex&amp;gt;\ sqrt{n}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Вывод&amp;quot; снести, он не нужен.&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
--[[Участник:Андрей Шулаев|Андрей Шулаев]] 14:05, 12 июня 2012 (GST)&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25263</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25263"/>
				<updated>2012-06-12T13:08:05Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&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;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&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;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&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; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&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;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При таком помещении сразу возникает следующая проблемой.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&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;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
# Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которая используется, находится следующим образом. Будут хэшироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хэшированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хэш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
А. Андерссон. Fast deterministic sorting and searching in linear space. Proc. 1996 IEEE Symp. on Foundations of Computer Science. 135-141(1996)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25261</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25261"/>
				<updated>2012-06-12T13:05:33Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом все числа отсортированы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку сортируется набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
# Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
# Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которая используется, находится следующим образом. Будут хэшироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хэшированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хэш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
А. Андерссон. Fast deterministic sorting and searching in linear space. Proc. 1996 IEEE Symp. on Foundations of Computer Science. 135-141(1996)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A5%D0%B0%D0%BD%D0%B0&amp;diff=25259</id>
		<title>Обсуждение:Сортировка Хана</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A5%D0%B0%D0%BD%D0%B0&amp;diff=25259"/>
				<updated>2012-06-12T13:02:41Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* &amp;lt;tex&amp;gt;log&amp;lt;/tex&amp;gt; -&amp;gt; &amp;lt;tex&amp;gt;\log&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Сокращение Э.П.дерево выглядит очень странно, лучше ЭП-дерево&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Если есть ещё какая-нибудь информация про это самое ЭП-дерево, добавить в ссылки&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Раздел &amp;quot;необходимая информация&amp;quot; лучше переименовать в &amp;quot;определения&amp;quot;, и вместо блоков с определениями сделать обычный список&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Определение контейнера какое-то странное, и ещё вместо __int32 и __int64 писать &amp;quot;32-битные числа&amp;quot; и &amp;quot;64-битные числа&amp;quot;&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Если мы&amp;quot;, &amp;quot;тогда мы&amp;quot; выглядит плохо. Лучше всего — писать обезличенно.&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
постарался убрать все &amp;quot;Если мы&amp;quot;, &amp;quot;тогда мы&amp;quot;, надеюсь вышло более-менее обезличенно&lt;br /&gt;
&lt;br /&gt;
* Посмотреть на четвёртое определение: я там дописал, как в техе записывать всякие минимумы, принадлежность множеству и т.д. Использовать такие формулы вместо текстовых описаний.&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
сделал где увидел&lt;br /&gt;
&lt;br /&gt;
* Вместо &amp;gt;= писать &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; (соответственно &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; вместо &amp;lt;=)&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
* Очень крупные абзацы в тексте, разбить на абзацы по-мельче&lt;br /&gt;
* Вместо ручной нумерации использовать вики-разметку&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
сделал где, по моему мнению, нужна была нумерация&lt;br /&gt;
&lt;br /&gt;
* Корень из n писать как &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
сделал везде, кроме одного заголовка, никак не получается выводить его как ссылку если писать как &amp;lt;tex&amp;gt;\ sqrt{n}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Вывод&amp;quot; снести, он не нужен.&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
--[[Участник:Андрей Шулаев|Андрей Шулаев]] 14:05, 12 июня 2012 (GST)&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25258</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25258"/>
				<updated>2012-06-12T13:01:11Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом все числа отсортированы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку сортируется набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которая используется, находится следующим образом. Будут хэшироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хэшированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хэш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
А. Андерссон. Fast deterministic sorting and searching in linear space. Proc. 1996 IEEE Symp. on Foundations of Computer Science. 135-141(1996)&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25256</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25256"/>
				<updated>2012-06-12T12:55:15Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом все числа отсортированы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку сортируется набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которая используется, находится следующим образом. Будут хэшироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хэшированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хэш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25255</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25255"/>
				<updated>2012-06-12T12:54:08Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом все числа отсортированы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку сортируется набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
## Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
## Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
## Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которая используется, находится следующим образом. Будут хэшироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хэшированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хэш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25253</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25253"/>
				<updated>2012-06-12T12:49:50Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым хранятся наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если сортируются целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда сортировка происходит с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; получаем хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если упаковать несколько чисел в один контейнер так, что они разделены несколькими битами нулей, спокойно применяется &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Рассматривается, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Необходимо разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. используется signature sorting, до того как делать вышеописанное разделение, необходимо поделить биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Так же делим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; берутся все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые берутся для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом преобразуется начальная задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Делим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как возможно делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, возможно упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, используем bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что используется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом берутся &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) разбираем и собираем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом все числа отсортированы.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O( \log n)&amp;lt;/tex&amp;gt; сортировка &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров произойдет за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Перемещаем каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе, содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров, упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;, упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Предполагая, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе можно использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Пренебрегая временем, потраченным на на эту упаковку, считается, что она бесплатна. По третьей лемме находим медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда убираем &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, затрачивается &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Используем &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому предполагается, что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. используется маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда используется вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда помещаем больше бит в набор, помещаются последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения предполагается, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того, как помещены эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор, удаляется изначальный текущий блок, потому, что известно, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку сортируется набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} предполагается, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Далее всегда считается, что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, вставляется не один элемент за раз, а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз. Алгоритм полностью опускает все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне опускаются &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как опустились все числа на следующий уровень и они успешно разделились на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем, берутся &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; и за раз и опускаются на следующий уровень ЭП-дерева. Это повторяется, пока все числа не опустятся на следующий уровень. На этом шаге числа разделены на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь числа опускаются дальше в ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Имеется &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень опускаются &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, то есть возможность использовать лемму 2 для сортировки. Для этого необходимо неконсервативное преимущество, которое получается ниже. Для этого используется линейная техника многократного деления (multi-dividing technique), чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и хотется использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом), чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, можно даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения, два контейнера объединяются в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые забиваются нулями. Сначала упаковываются все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом получилось дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как повторится вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз, получится неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время, как потрачено только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которая используется, находится следующим образом. Будут хэшироватся сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число, получится &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то, получится не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагается, что хэшированные значения для каждого контейнера упаковались в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Комбинируя все хэш контейнеры в один pool, сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
# Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
# Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом заполняются все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит получаем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора собираются все его поднаборы в подзадачах в один набор. Затем используя лемму два, делается разделение. Так как получено неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и работа происходит на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
В итоге разделились &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть, получилось, что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора делается следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которая решается следующим образом. Считается, что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. Ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25238</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25238"/>
				<updated>2012-06-12T12:12:50Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект, в которым мы храним наши данные. Например: 32-битные и 64-битные числа, массивы, вектора.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O( \log n)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень ЭП-дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые мы забиваем нулями. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которую решим следующим образом. Будем считать что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. мы ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25235</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25235"/>
				<updated>2012-06-12T12:09:58Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O( \log n)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень ЭП-дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые мы забиваем нулями. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которую решим следующим образом. Будем считать что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. мы ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25234</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25234"/>
				<updated>2012-06-12T12:09:26Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Определения== &lt;br /&gt;
# Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
# Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
# Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
# Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\max(S) = \max\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;\max(S1) \le \min(S2)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O( \log n)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень ЭП-дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые мы забиваем нулями. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которую решим следующим образом. Будем считать что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. мы ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25229</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25229"/>
				<updated>2012-06-12T11:57:06Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} ЭП-дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в ЭП-дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
ЭП-дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) ЭП-поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое ЭП-поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O( \log n)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое ЭП-дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень ЭП-дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем ЭП-дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному ЭП-дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни ЭП-дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из ЭП-дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые мы забиваем нулями. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которую решим следующим образом. Будем считать что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в ЭП-дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. мы ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25226</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25226"/>
				<updated>2012-06-12T11:54:44Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O( \log n)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые мы забиваем нулями. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которую решим следующим образом. Будем считать что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в Э.П.дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. мы ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25224</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25224"/>
				<updated>2012-06-12T11:52:06Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; \ge 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) \le min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b \ge 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; \ge &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; \ge 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; \ge &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) \le t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O( \log n)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g \le \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;\log m \ge \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;\le &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в \le 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt \ge n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые мы забиваем нулями. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которую решим следующим образом. Будем считать что число бит в контейнере &amp;lt;tex&amp;gt;\log m \ge \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в Э.П.дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. мы ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A5%D0%B0%D0%BD%D0%B0&amp;diff=25221</id>
		<title>Обсуждение:Сортировка Хана</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A5%D0%B0%D0%BD%D0%B0&amp;diff=25221"/>
				<updated>2012-06-12T11:50:36Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* &amp;lt;tex&amp;gt;log&amp;lt;/tex&amp;gt; -&amp;gt; &amp;lt;tex&amp;gt;\log&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
* Сокращение Э.П.дерево выглядит очень странно, лучше ЭП-дерево&lt;br /&gt;
* Если есть ещё какая-нибудь информация про это самое ЭП-дерево, добавить в ссылки&lt;br /&gt;
* Раздел &amp;quot;необходимая информация&amp;quot; лучше переименовать в &amp;quot;определения&amp;quot;, и вместо блоков с определениями сделать обычный список&lt;br /&gt;
* Определение контейнера какое-то странное, и ещё вместо __int32 и __int64 писать &amp;quot;32-битные числа&amp;quot; и &amp;quot;64-битные числа&amp;quot;&lt;br /&gt;
* &amp;quot;Если мы&amp;quot;, &amp;quot;тогда мы&amp;quot; выглядит плохо. Лучше всего — писать обезличенно.&lt;br /&gt;
* Посмотреть на четвёртое определение: я там дописал, как в техе записывать всякие минимумы, принадлежность множеству и т.д. Использовать такие формулы вместо текстовых описаний.&lt;br /&gt;
* Вместо &amp;gt;= писать &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; (соответственно &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; вместо &amp;lt;=)&lt;br /&gt;
* Очень крупные абзацы в тексте, разбить на абзацы по-мельче&lt;br /&gt;
* Вместо ручной нумерации использовать вики-разметку&lt;br /&gt;
* Корень из n писать как &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
&lt;br /&gt;
сделал везде, кроме одного заголовка, никак не получается выводить его как ссылку если писать как &amp;lt;tex&amp;gt;\ sqrt{n}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* &amp;quot;Вывод&amp;quot; снести, он не нужен.&lt;br /&gt;
&lt;br /&gt;
готово&lt;br /&gt;
--[[Участник:Андрей Шулаев|Андрей Шулаев]] 14:05, 12 июня 2012 (GST)&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A5%D0%B0%D0%BD%D0%B0&amp;diff=25220</id>
		<title>Обсуждение:Сортировка Хана</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A5%D0%B0%D0%BD%D0%B0&amp;diff=25220"/>
				<updated>2012-06-12T11:49:15Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* &amp;lt;tex&amp;gt;log&amp;lt;/tex&amp;gt; -&amp;gt; &amp;lt;tex&amp;gt;\log&amp;lt;/tex&amp;gt;&lt;br /&gt;
готово&lt;br /&gt;
* Сокращение Э.П.дерево выглядит очень странно, лучше ЭП-дерево&lt;br /&gt;
* Если есть ещё какая-нибудь информация про это самое ЭП-дерево, добавить в ссылки&lt;br /&gt;
* Раздел &amp;quot;необходимая информация&amp;quot; лучше переименовать в &amp;quot;определения&amp;quot;, и вместо блоков с определениями сделать обычный список&lt;br /&gt;
* Определение контейнера какое-то странное, и ещё вместо __int32 и __int64 писать &amp;quot;32-битные числа&amp;quot; и &amp;quot;64-битные числа&amp;quot;&lt;br /&gt;
* &amp;quot;Если мы&amp;quot;, &amp;quot;тогда мы&amp;quot; выглядит плохо. Лучше всего — писать обезличенно.&lt;br /&gt;
* Посмотреть на четвёртое определение: я там дописал, как в техе записывать всякие минимумы, принадлежность множеству и т.д. Использовать такие формулы вместо текстовых описаний.&lt;br /&gt;
* Вместо &amp;gt;= писать &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; (соответственно &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; вместо &amp;lt;=)&lt;br /&gt;
* Очень крупные абзацы в тексте, разбить на абзацы по-мельче&lt;br /&gt;
* Вместо ручной нумерации использовать вики-разметку&lt;br /&gt;
* Корень из n писать как &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
готово&lt;br /&gt;
сделал везде, кроме одного заголовка, никак не получается выводить его как ссылку если писать как &amp;lt;tex&amp;gt;sqrt{n}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
* &amp;quot;Вывод&amp;quot; снести, он не нужен.&lt;br /&gt;
готово&lt;br /&gt;
--[[Участник:Андрей Шулаев|Андрей Шулаев]] 14:05, 12 июня 2012 (GST)&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25217</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25217"/>
				<updated>2012-06-12T11:47:13Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O( \log n)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;\log m &amp;gt;= \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые мы забиваем нулями. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которую решим следующим образом. Будем считать что число бит в контейнере &amp;lt;tex&amp;gt;\log m &amp;gt;= \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в Э.П.дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. мы ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A5%D0%B0%D0%BD%D0%B0&amp;diff=25216</id>
		<title>Обсуждение:Сортировка Хана</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D0%A5%D0%B0%D0%BD%D0%B0&amp;diff=25216"/>
				<updated>2012-06-12T11:44:51Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* &amp;lt;tex&amp;gt;log&amp;lt;/tex&amp;gt; -&amp;gt; &amp;lt;tex&amp;gt;\log&amp;lt;/tex&amp;gt;&lt;br /&gt;
готово&lt;br /&gt;
* Сокращение Э.П.дерево выглядит очень странно, лучше ЭП-дерево&lt;br /&gt;
* Если есть ещё какая-нибудь информация про это самое ЭП-дерево, добавить в ссылки&lt;br /&gt;
* Раздел &amp;quot;необходимая информация&amp;quot; лучше переименовать в &amp;quot;определения&amp;quot;, и вместо блоков с определениями сделать обычный список&lt;br /&gt;
* Определение контейнера какое-то странное, и ещё вместо __int32 и __int64 писать &amp;quot;32-битные числа&amp;quot; и &amp;quot;64-битные числа&amp;quot;&lt;br /&gt;
* &amp;quot;Если мы&amp;quot;, &amp;quot;тогда мы&amp;quot; выглядит плохо. Лучше всего — писать обезличенно.&lt;br /&gt;
* Посмотреть на четвёртое определение: я там дописал, как в техе записывать всякие минимумы, принадлежность множеству и т.д. Использовать такие формулы вместо текстовых описаний.&lt;br /&gt;
* Вместо &amp;gt;= писать &amp;lt;tex&amp;gt;\ge&amp;lt;/tex&amp;gt; (соответственно &amp;lt;tex&amp;gt;\le&amp;lt;/tex&amp;gt; вместо &amp;lt;=)&lt;br /&gt;
* Очень крупные абзацы в тексте, разбить на абзацы по-мельче&lt;br /&gt;
* Вместо ручной нумерации использовать вики-разметку&lt;br /&gt;
* Корень из n писать как &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
* &amp;quot;Вывод&amp;quot; снести, он не нужен.&lt;br /&gt;
--[[Участник:Андрей Шулаев|Андрей Шулаев]] 14:05, 12 июня 2012 (GST)&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25215</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25215"/>
				<updated>2012-06-12T11:43:57Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O( \log n)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в &amp;lt;tex&amp;gt;sqrt(n)&amp;lt;/tex&amp;gt; наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;\log m &amp;gt;= \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые мы забиваем нулями. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которую решим следующим образом. Будем считать что число бит в контейнере &amp;lt;tex&amp;gt;\log m &amp;gt;= \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в Э.П.дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. мы ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Вывод==&lt;br /&gt;
Таким образом имеем:&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=th1. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел могут быть отсортированы за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25214</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25214"/>
				<updated>2012-06-12T11:42:20Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;k \log (m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2 \log n&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;\log m&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2h \log n&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt; \log (m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;\log (m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(n \log g/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (\log n)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(g \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g) \log g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O( \log n)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g) \log\log n)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt; \log m &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((n \log\log n)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;( \log n)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;\log m \log\log n &amp;gt; \log n&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(\log m)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(\log n)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(g \log\log n)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g \log\log n&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;\log m \log\log n&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= \log n&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;k \log\log n \log m&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;k \log \log n&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;\log m &amp;gt;= \log n \log\log n&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;\log m&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;i \log m/ \log n&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1) \log m/ \log n - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;\log n - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/ \log n)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;\log m/ \log n&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/ \log n&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2 \log n&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;\log n/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;\log n/(2\log e)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = \log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;k \log\log n \log n&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(k \log n/g) = O(k \log e)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;\log e&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;\log n/(2 \log e)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(\log n)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((n \log e)/ \log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;k \log e&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;k \log\log n&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;\log_{k}((\log n)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(n \log\log n/ \log k)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(n \log\log n) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(\log (m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = \log n/(c \log p)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/ \log\log n \log p&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(\log n)/(c \log\log n)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/ \log\log n&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые мы забиваем нулями. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&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; разрезаны на &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;\log\log n/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(\log\log n/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(\log\log n/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(\log\log n/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; \log n&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;\log n&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2 \log n)/(c \log\log n)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/ \log\log n)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2 \log\log\log n&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qt \log\log n/(g(\log h - \log\log\log n) - \log\log\log n)) = O(\log\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которую решим следующим образом. Будем считать что число бит в контейнере &amp;lt;tex&amp;gt;\log m &amp;gt;= \log\log\log n&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/ \log\log n&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;\log h&amp;lt;/tex&amp;gt; в Э.П.дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2 \log n)(c \log\log n)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/ \log\log n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{\log\log n, 1}0^{j}t_{1, 2}...t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/ \log\log n&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. мы ипользуем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов, чтобы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/ \log\log n}t_{1, 1}t_{2, 1} ... t_{\log\log n, 1}t_{1, 2}t_{2, 2} ... t_{1, h/ \log\log n}t_{2, h/ \log\log n} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2 \log n/c&amp;lt;/tex&amp;gt; бит. Мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/ \log\log n}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/ \log\log n} k = 1, 2, ..., \log\log n&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/ \log\log n}0^{r}t_{2, 1} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/ \log\log n}t_{2, 1}t_{2, 2} ... t_{\log\log n, h/ \log\log n}&amp;lt;/tex&amp;gt;. В итоге мы используем &amp;lt;tex&amp;gt;O(\log\log n)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;\log\log n&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Вывод==&lt;br /&gt;
Таким образом имеем:&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=th1. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел могут быть отсортированы за время &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; и линейную память.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(n \log\log n) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25210</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25210"/>
				<updated>2012-06-12T11:22:05Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(n\log\log n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n\log\logn)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n\log\logn)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
&amp;lt;tex&amp;gt;\min(S) = \min\limits_{a \in S} a&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(log(m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = logn/(clogp)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/loglognlogp&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(logn)/(cloglogn)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/loglogn&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые мы забиваем нулями. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&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; разрезаны на &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(loglogn/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(loglogn/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; logn&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2logloglogn&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qtloglogn/(g(logh - logloglogn) -logloglogn)) = O(loglogn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которую решим следующим образом. Будем считать что число бит в контейнере &amp;lt;tex&amp;gt;logm &amp;gt;= logloglogn&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;logh&amp;lt;/tex&amp;gt; в Э.П.дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2logn)(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/loglogn}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем loglogn контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{loglogn, 1}0^{j}t_{1, 2}...t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/loglogn&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. мы ипользуем &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; шагов, чтбы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/loglogn}t_{1, 1}t_{2, 1} ... t_{loglogn, 1}t_{1, 2}t_{2, 2} ... t_{1, h/loglogn}t_{2, h/loglogn} ... t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2logn/c&amp;lt;/tex&amp;gt; бит. Мы используем &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/loglogn}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/loglogn} k = 1, 2, ..., loglogn&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/loglogn}0^{r}t_{2, 1} ... t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/loglogn}t_{2, 1}t_{2, 2} ... t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt;. В итоге мы используем &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Вывод==&lt;br /&gt;
Таким образом имеем:&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=th1. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел могут быть отсортированы за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(nloglogn) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25155</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25155"/>
				<updated>2012-06-12T04:12:56Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(log(m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = logn/(clogp)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/loglognlogp&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(logn)/(cloglogn)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/loglogn&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые мы забиваем нулями. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&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; разрезаны на &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(loglogn/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(loglogn/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; logn&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2logloglogn&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qtloglogn/(g(logh - logloglogn) -logloglogn)) = O(loglogn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которую решим следующим образом. Будем считать что число бит в контейнере &amp;lt;tex&amp;gt;logm &amp;gt;= logloglogn&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;logh&amp;lt;/tex&amp;gt; в Э.П.дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2logn)(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/loglogn}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем loglogn контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{loglogn, 1}0^{j}t_{1, 2}...t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/loglogn&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. мы ипользуем &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; шагов, чтбы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/loglogn}t_{1, 1}t_{2, 1} ... t_{loglogn, 1}t_{1, 2}t_{2, 2} ... t_{1, h/loglogn}t_{2, h/loglogn} ... t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2logn/c&amp;lt;/tex&amp;gt; бит. Мы используем &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/loglogn}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/loglogn} k = 1, 2, ..., loglogn&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/loglogn}0^{r}t_{2, 1} ... t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/loglogn}t_{2, 1}t_{2, 2} ... t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt;. В итоге мы используем &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Вывод==&lt;br /&gt;
Таким образом имеем:&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=th1. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел могут быть отсортированы за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Литераура==&lt;br /&gt;
Deterministic Sorting in O(nloglogn) Time and Linear Space. Yijie Han.&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25154</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25154"/>
				<updated>2012-06-12T04:10:37Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(log(m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = logn/(clogp)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/loglognlogp&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(logn)/(cloglogn)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/loglogn&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые мы забиваем нулями. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&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; разрезаны на &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(loglogn/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(loglogn/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; logn&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2logloglogn&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qtloglogn/(g(logh - logloglogn) -logloglogn)) = O(loglogn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которую решим следующим образом. Будем считать что число бит в контейнере &amp;lt;tex&amp;gt;logm &amp;gt;= logloglogn&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;logh&amp;lt;/tex&amp;gt; в Э.П.дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2logn)(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/loglogn}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем loglogn контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{loglogn, 1}0^{j}t_{1, 2}...t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/loglogn&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. мы ипользуем &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; шагов, чтбы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/loglogn}t_{1, 1}t_{2, 1} ... t_{loglogn, 1}t_{1, 2}t_{2, 2} ... t_{1, h/loglogn}t_{2, h/loglogn} ... t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2logn/c&amp;lt;/tex&amp;gt; бит. Мы используем &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/loglogn}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/loglogn} k = 1, 2, ..., loglogn&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/loglogn}0^{r}t_{2, 1} ... t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/loglogn}t_{2, 1}t_{2, 2} ... t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt;. В итоге мы используем &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Вывод==&lt;br /&gt;
Таким образом имеем:&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=th1. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел могут быть отсортированы за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Сортировки]]&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25153</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25153"/>
				<updated>2012-06-12T04:08:20Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(log(m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = logn/(clogp)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/loglognlogp&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(logn)/(cloglogn)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/loglogn&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые мы забиваем нулями. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&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; разрезаны на &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(loglogn/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(loglogn/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; logn&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2logloglogn&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qtloglogn/(g(logh - logloglogn) -logloglogn)) = O(loglogn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которую решим следующим образом. Будем считать что число бит в контейнере &amp;lt;tex&amp;gt;logm &amp;gt;= logloglogn&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;logh&amp;lt;/tex&amp;gt; в Э.П.дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2logn)(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/loglogn}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем loglogn контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{loglogn, 1}0^{j}t_{1, 2}...t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/loglogn&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. мы ипользуем &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; шагов, чтбы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/loglogn}t_{1, 1}t_{2, 1} ... t_{loglogn, 1}t_{1, 2}t_{2, 2} ... t_{1, h/loglogn}t_{2, h/loglogn} ... t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2logn/c&amp;lt;/tex&amp;gt; бит. Мы используем &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; времени чтобы распаковать &amp;lt;tex&amp;gt;w_{2}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров &amp;lt;tex&amp;gt;w_{3, k} = 0^{jh/loglogn}0^{r}t_{k, 1}O^{r}t_{k, 2} ... t_{k, h/loglogn} k = 1, 2, ..., loglogn&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; времени упаковываем эти &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один &amp;lt;tex&amp;gt;w_{4} = 0^{r}t_{1, 1}0^{r}t_{1, 2} ... t_{1, h/loglogn}0^{r}t_{2, 1} ... t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt;. Затем используя &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; шагов упаковать &amp;lt;tex&amp;gt;w_{4}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{5} = 0^{s}t_{1, 1}t_{1, 2} ... t_{1, h/loglogn}t_{2, 1}t_{2, 2} ... t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt;. В итоге мы используем &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; времени для упаковки &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров. Считаем что время потраченное на одно слово {{---}} константа.&lt;br /&gt;
&lt;br /&gt;
==Вывод==&lt;br /&gt;
Таким образом имеем:&lt;br /&gt;
{{Теорема&lt;br /&gt;
|id=th1. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел могут быть отсортированы за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память.&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25152</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25152"/>
				<updated>2012-06-12T03:52:03Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(log(m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = logn/(clogp)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/loglognlogp&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(logn)/(cloglogn)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/loglogn&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; бит в каждом контейнере. Между сегментами получаются пустоты, которые мы забиваем нулями. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&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; разрезаны на &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(loglogn/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(loglogn/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; logn&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2logloglogn&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qtloglogn/(g(logh - logloglogn) -logloglogn)) = O(loglogn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;br /&gt;
&lt;br /&gt;
Теперь рассмотрим проблему упаковки, которую решим следующим образом. Будем считать что число бит в контейнере &amp;lt;tex&amp;gt;logm &amp;gt;= logloglogn&amp;lt;/tex&amp;gt;, потому, что в противном случае можно использовать radix sort для сортировки чисел. У контейнера есть &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений (сегментов) в себе на уровне &amp;lt;tex&amp;gt;logh&amp;lt;/tex&amp;gt; в Э.П.дереве. Полное число хэшированных бит в контейнере &amp;lt;tex&amp;gt;(2logn)(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя хэшированны биты в контейнере выглядят как &amp;lt;tex&amp;gt;0^{i}t_{1}0^{i}t_{2}...t_{h/loglogn}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;t_{k}&amp;lt;/tex&amp;gt;-ые это хэшированные биты, а нули это просто нули. Сначала упаковываем loglogn контейнеров в один и получаем &amp;lt;tex&amp;gt;w_{1} = 0^{j}t_{1, 1}t_{2, 1}...t_{loglogn, 1}0^{j}t_{1, 2}...t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt;t_{i, k}&amp;lt;/tex&amp;gt;: &amp;lt;tex&amp;gt;k = 1, 2, ..., h/loglogn&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ого контейнера. мы ипользуем &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; шагов, чтбы упаковать &amp;lt;tex&amp;gt;w_{1}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;w_{2} = 0^{jh/loglogn}t_{1, 1}t_{2, 1} ... t_{loglogn, 1}t_{1, 2}t_{2, 2} ... t_{1, h/loglogn}t_{2, h/loglogn} ... t_{loglogn, h/loglogn}&amp;lt;/tex&amp;gt;. Теперь упакованные хэш биты занимают &amp;lt;tex&amp;gt;2logn/c&amp;lt;/tex&amp;gt; бит. Мы используем &amp;lt;tex&amp;gt;O(loglogn)&amp;lt;/tex&amp;gt; времени&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25151</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25151"/>
				<updated>2012-06-12T03:31:56Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(log(m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = logn/(clogp)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/loglognlogp&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(logn)/(cloglogn)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/loglogn&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; бит в каждом контейнере. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&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; разрезаны на &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(loglogn/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(loglogn/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; logn&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2logloglogn&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qtloglogn/(g(logh - logloglogn) -logloglogn)) = O(loglogn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Мы разделили &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами в каждый набор. То есть мы получили &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;e_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;e_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;e_{i}&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;S_{i}&amp;lt;/tex&amp;gt; предшествуют числам в &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; если &amp;lt;tex&amp;gt;i &amp;lt; j&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;e_{i}&amp;lt;/tex&amp;gt; хранится после &amp;lt;tex&amp;gt;S_{i - 1}&amp;lt;/tex&amp;gt; но до &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Пусть &amp;lt;tex&amp;gt;B[i]&amp;lt;/tex&amp;gt; в поднаборе &amp;lt;tex&amp;gt;B[i].subset&amp;lt;/tex&amp;gt;. Чтобы позволить разделению выполнится для каждого поднабора мы делаем следующее. &lt;br /&gt;
&lt;br /&gt;
Помещаем все &amp;lt;tex&amp;gt;B[j]&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;B[j].subset&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На это потребуется линейное время и место.&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25150</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25150"/>
				<updated>2012-06-12T03:16:48Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(log(m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = logn/(clogp)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/loglognlogp&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(logn)/(cloglogn)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/loglogn&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; бит в каждом контейнере. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&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; разрезаны на &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(loglogn/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(loglogn/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; logn&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;br /&gt;
&lt;br /&gt;
Как уже говорилось ранее после &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; сокращений бит мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt;. Мы не волнуемся об этих сокращениях до конца потому, что после получения неконсервативного преимущества мы можем переключиться на лемму два для завершения разделения &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел с помощью &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на наборы. Заметим, что по природе битового сокращения, начальная задача разделения для каждого набора перешла в &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; подзадачи разделения на &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt; поднаборы для какого-то числа &amp;lt;tex&amp;gt;w&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь для каждого набора мы собираем все его поднаборы в подзадачах в один набор. Затем используя лемму два делаем разделение. Так как мы имеем неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; и мы работаем на уровнях не ниже чем &amp;lt;tex&amp;gt;2logloglogn&amp;lt;/tex&amp;gt;, то алгоритм занимает &amp;lt;tex&amp;gt;O(qtloglogn/(g(logh - logloglogn) -logloglogn)) = O(loglogn)&amp;lt;/tex&amp;gt; времени.&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25149</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25149"/>
				<updated>2012-06-12T03:00:57Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(log(m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = logn/(clogp)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/loglognlogp&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(logn)/(cloglogn)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/loglogn&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; бит в каждом контейнере. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&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; разрезаны на &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(loglogn/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(loglogn/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; logn&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее. Предполагаем, что мы упаковали хэшированные значения для каждого контейнера в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. У нас есть &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов в каждом из которых &amp;lt;tex&amp;gt;q + p&amp;lt;/tex&amp;gt; хэшированных контейнеров по &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит в каждом. Эти числа должны быть отсортированы в каждом наборе. Мы комбинируем все хэш контейнеры в один pool и сортируем следующим образом.&lt;br /&gt;
&lt;br /&gt;
Procedure linear-Time-Sort&lt;br /&gt;
&lt;br /&gt;
Входные данные: &amp;lt;tex&amp;gt;r &amp;gt; = n^{2/5}&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value значение числа &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; в котором &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит, &amp;lt;tex&amp;gt;d_{i}.set&amp;lt;/tex&amp;gt; набор, в котором находится &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;, следует отметить что всего &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; наборов.&lt;br /&gt;
&lt;br /&gt;
1) Сортировать все &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt; по &amp;lt;tex&amp;gt;d_{i}&amp;lt;/tex&amp;gt;.value используя bucket sort. Пусть все сортированные числа в A[1..r]. Этот шаг занимает линейное время так как сортируется не менее &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел.&lt;br /&gt;
&lt;br /&gt;
2) Поместить все A[j] в A[j].set&lt;br /&gt;
&lt;br /&gt;
Таким образом мы заполнили все наборы за линейное время.&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25148</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25148"/>
				<updated>2012-06-12T02:47:24Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(log(m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = logn/(clogp)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/loglognlogp&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(logn)/(cloglogn)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/loglogn&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; бит в каждом контейнере. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&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; разрезаны на &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;br /&gt;
&lt;br /&gt;
После того, как мы повторили вышеописанный процесс &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; раз мы получили неконсервативное преимущество в &amp;lt;tex&amp;gt;(h/loglogn)^g&amp;lt;/tex&amp;gt; раз, в то время как мы потратили только &amp;lt;tex&amp;gt;O(gqt)&amp;lt;/tex&amp;gt; времени, так как каждое многократное деление делятся за линейное время &amp;lt;tex&amp;gt;O(qt)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Хэш функция, которую мы используем, находится следующим образом. Мы будем хэшировать сегменты, которые &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;-ые, &amp;lt;tex&amp;gt;(loglogn/h)^2&amp;lt;/tex&amp;gt;-ые, ... от всего числа. Для сегментов вида &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt;, получаем нарезанием всех &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел на &amp;lt;tex&amp;gt;(loglogn/h)^t&amp;lt;/tex&amp;gt; сегментов. Рассматривая каждый сегмент как число мы получаем &amp;lt;tex&amp;gt;p(loglogn/h)^t&amp;lt;/tex&amp;gt; чисел. Затем получаем одну хэш функцию для этих чисел. Так как &amp;lt;tex&amp;gt;t &amp;lt; logn&amp;lt;/tex&amp;gt; то мы получим не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; хэш функций.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим сортировку за линейное время о которой было упомянуто ранее.&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25147</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25147"/>
				<updated>2012-06-12T02:33:20Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(log(m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас. Предположим у нас есть набор &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел, которые уже отсортированы как &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt;, и мы хотим использовать числа в &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; для разделения &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;b_{1}, b_{2}, ..., b_{q}&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; что &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Назовем это разделением &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами. Пусть &amp;lt;tex&amp;gt;h = logn/(clogp)&amp;lt;/tex&amp;gt; для константы &amp;lt;tex&amp;gt;c &amp;gt; 1&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;h/loglognlogp&amp;lt;/tex&amp;gt; битные числа могут быть хранены в одном контейнере, так что одно слово хранит &amp;lt;tex&amp;gt;(logn)/(cloglogn)&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; как сегменты одинаковой длины &amp;lt;tex&amp;gt;h/loglogn&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;-ом) чтобы получить &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; хэшированных значений в одном контейнере. Чтобы получить значения сразу, при вычислении хэш значений сегменты не влияют друг на друга, мы можем даже отделить четные и нечетные сегменты в два контейнера. Не умаляя общности считаем, что хэш значения считаются за константное время. Затем, посчитав значения мы объединяем два контейнера в один. Пусть &amp;lt;tex&amp;gt;a'_{i}&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;. В сумме хэш значения имеют &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&amp;lt;/tex&amp;gt; бит. Хотя эти значения разделены на сегменты по &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; бит в каждом контейнере. Сначала упаковываем все сегменты в &amp;lt;tex&amp;gt;(2logn)/(cloglogn)&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; разрезаны на &amp;lt;tex&amp;gt;loglogn/h&amp;lt;/tex&amp;gt;. Таким образом мы получили дополнительное мультипликативное преимущество в &amp;lt;tex&amp;gt;h/loglogn&amp;lt;/tex&amp;gt; (additional multiplicative advantage).&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25146</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25146"/>
				<updated>2012-06-12T02:08:12Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(log(m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;br /&gt;
&lt;br /&gt;
Спуск вниз можно рассматривать как сортировку &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел в каждом наборе вместе с &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; числами &amp;lt;tex&amp;gt;a_{1}, a_{2}, ..., a_{p}&amp;lt;/tex&amp;gt; из Э.П.дерева, так, что эти &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел разделены в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{0}, S_{1}, ..., S_{p}&amp;lt;/tex&amp;gt; таких, что &amp;lt;tex&amp;gt;S_{0} &amp;lt; &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;}&amp;lt;tex&amp;gt; &amp;lt; S_{p}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как нам не надо полностью сортировать &amp;lt;tex&amp;gt;q&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;q = p^2&amp;lt;/tex&amp;gt;, есть возможность использовать лемму 2 для сортировки. Для этого нам надо неконсервативное преимущество которое мы получим ниже. Для этого используем линейную технику многократного деления (multi-dividing technique) чтобы добиться этого.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся signature sorting. Адаптируем этот алгоритм для нас.&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25145</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25145"/>
				<updated>2012-06-12T01:57:08Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка n целых чисел в sqrt(n) наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием O(nloglogn) времени и памяти==&lt;br /&gt;
Для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в диапазоне от {&amp;lt;tex&amp;gt;0, 1, ..., m - 1&amp;lt;/tex&amp;gt;} мы предполагаем, что используем контейнер длины &amp;lt;tex&amp;gt;O(log(m + n))&amp;lt;/tex&amp;gt; в нашем консервативном алгоритме. Мы всегда считаем что все числа упакованы в контейнеры одинаковой длины. &lt;br /&gt;
&lt;br /&gt;
Берем &amp;lt;tex&amp;gt;1/e = 5&amp;lt;/tex&amp;gt; для экспоненциального поискового дереве Андерссона. Поэтому у корня будет &amp;lt;tex&amp;gt;n^{1/5}&amp;lt;/tex&amp;gt; детей и каждое Э.П.дерево в каждом ребенке будет иметь &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; листьев. В отличии от оригинального дерева, мы будем вставлять не один элемент за раз а &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; {{---}} количество детей узла дерева, где числа должны спуститься вниз.&lt;br /&gt;
Но мы не будем сразу опускать донизу все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел. Мы будем полностью опускать все &amp;lt;tex&amp;gt;d^2&amp;lt;/tex&amp;gt; чисел на один уровень. В корне мы опустим &amp;lt;tex&amp;gt;n^{2/5}&amp;lt;/tex&amp;gt; чисел на следующий уровень. После того, как мы опустили все числа на следующий уровень мы успешно разделили числа на &amp;lt;tex&amp;gt;t_{1} = n^{1/5}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}, S_{2}, ..., S_{t_{1}}&amp;lt;/tex&amp;gt;, в каждом из которых &amp;lt;tex&amp;gt;n^{4/5}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i} &amp;lt; S_{j}, i &amp;lt; j&amp;lt;/tex&amp;gt;. Затем мы берем &amp;lt;tex&amp;gt;n^{(4/5)(2/5)}&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; за раз и опускаем их на следующий уровень Э.П.дерева. Повторяем это, пока все числа не опустятся на следующий уровень. На этом шаге мы разделили числа на &amp;lt;tex&amp;gt;t_{2} = n^{1/5}n^{4/25} = n^{9/25}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;T_{1}, T_{2}, ..., T_{t_{2}}&amp;lt;/tex&amp;gt; в каждом из которых &amp;lt;tex&amp;gt;n^{16/25}&amp;lt;/tex&amp;gt; чисел, аналогичным наборам &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt;. Теперь мы можем дальше опустить числа в нашем Э.П.дереве.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что ребалансирока занимает &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; времени с &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; временем на уровень. Аналогично стандартному Э.П.дереву Андерссона.&lt;br /&gt;
&lt;br /&gt;
Нам следует нумеровать уровни Э.П.дерева с корня, начиная с нуля. Рассмотрим спуск вниз на уровне &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Мы имеем &amp;lt;tex&amp;gt;t = n^{1 - (4/5)^s}&amp;lt;/tex&amp;gt; наборов по &amp;lt;tex&amp;gt;n^{(4/5)^s}&amp;lt;/tex&amp;gt; чисел в каждом. Так как каждый узел на данном уровне имеет &amp;lt;tex&amp;gt;p = n^{(1/5)(4/5)^s}&amp;lt;/tex&amp;gt; детей, то на &amp;lt;tex&amp;gt;s + 1&amp;lt;/tex&amp;gt; уровень мы опустим &amp;lt;tex&amp;gt;q = n^{(2/5)(4/5)^s}&amp;lt;/tex&amp;gt; чисел для каждого набора или всего &amp;lt;tex&amp;gt;qt &amp;gt;= n^{2/5}&amp;lt;/tex&amp;gt; чисел для всех наборов за один раз.&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25144</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25144"/>
				<updated>2012-06-12T01:24:40Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
начало&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = &amp;lt;/tex&amp;gt;{&amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;}, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
конец&lt;br /&gt;
&lt;br /&gt;
Время работы алгоритма &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt;, что доказывает лемму 2.&lt;br /&gt;
&lt;br /&gt;
==Собственно сортировка с использованием &amp;lt;tex&amp;gt;O(nloglogn) времени и памяти&amp;lt;/tex&amp;gt;==&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25143</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25143"/>
				<updated>2012-06-12T01:16:06Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если размер меньше или равен &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;return&amp;lt;/tex&amp;gt;. Иначе разделить этот набор в &amp;lt;= 3 набора используя лемму три, чтобы найти медиану а затем использовать лемму 6 для сортировки. Для набора где все элементы равны медиане, не рассматривать текущий блок и текущим блоком сделать следующий. Создать маркер, являющийся номером набора для каждого из чисел (0, 1 или 2). Затем направьте маркер для каждого числа назад к месту, где число находилось в начале. Также направьте двубитное число для каждого входного числа, указывающее на текущий блок. &amp;lt;tex&amp;gt;Return&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;br /&gt;
&lt;br /&gt;
От &amp;lt;tex&amp;gt;u = 1&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.1) Упаковать &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt;-ый в часть из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых номеров контейнеров, где &amp;lt;tex&amp;gt;a^{(u)}_{i}&amp;lt;/tex&amp;gt; содержит несколько непрерывных блоков, которые состоят из &amp;lt;tex&amp;gt;1/k&amp;lt;/tex&amp;gt;-ых битов &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и у которого текущий блок это самый крупный блок.&lt;br /&gt;
&lt;br /&gt;
2.2) Вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level - 1&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a^{(u)}_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a^{(u)}_{t}&amp;lt;/tex&amp;gt;). Когда алгоритм возвращается из этой рекурсии, маркер, показывающий для каждого числа, к которому набору это число относится, уже отправлен назад к месту где число находится во входных данных. Число имеющее наибольшее число бит в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, показывающее на ткущий блок в нем, так же отправлено назад к &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2.3) Отправить &amp;lt;tex&amp;gt;a_{i}-ые к их наборам, используя лемму шесть.&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Algorithm IterateSort&lt;br /&gt;
Call Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{n - 1}&amp;lt;/tex&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
от 1 до 5&lt;br /&gt;
&lt;br /&gt;
Поместить &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; в соответствующий набор с помощью bucket sort потому, что наборов около &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого набора &amp;lt;tex&amp;gt;S = {a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}}&amp;lt;/tex&amp;gt;, если &amp;lt;tex&amp;gt;t &amp;gt; sqrt{n}&amp;lt;/tex&amp;gt;, то вызвать Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;log_{k}((logn)/4)&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{i_{0}}, a_{i_{1}}, ..., a_{i_{t}}&amp;lt;/tex&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25142</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25142"/>
				<updated>2012-06-12T00:31:52Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&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;i&amp;lt;/tex&amp;gt;-ым в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Рассмотрим блок &amp;lt;tex&amp;gt;a&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;-ым м.ч. в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Когда мы используем вышеописанный метод перемещения нескольких следующих блоков &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; (назовем это &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;) в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt; просто перемещен на позицию в наборе &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, но не обязательно на позицию &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (где расположен &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt;). Если значение блока &amp;lt;tex&amp;gt;a'&amp;lt;/tex&amp;gt; одинаково для всех чисел в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, то это не создаст проблемы потому, что блок одинаков вне зависимости от того в какое место в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; помещен &amp;lt;tex&amp;gt;a''&amp;lt;/tex&amp;gt;. Иначе у нас возникает проблема дальнейшей сортировки. Поэтому мы поступаем следующим образом: На каждой стадии числа в одном наборе работают на общем блоке, который назовем &amp;quot;текущий блок набора&amp;quot;. Блоки, которые предшествуют текущему блоку содержат важные биты и идентичны для всех чисел в наборе. Когда мы помещаем больше бит в набор мы помещаем последующие блоки вместе с текущим блоком в набор. Так вот, в вышеописанном процессе помещения мы предполагаем, что самый значимый блок среди &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков это текущий блок. Таким образом после того как мы поместили эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков в набор мы удаляем изначальный текущий блок, потому что мы знаем, что эти &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков перемещены в правильный набор и нам не важно где находился начальный текущий блок. Тот текущий блок находится в перемещенных &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоках.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что после нескольких уровней деления размер наборов станет маленьким. Леммы четыре, пять и шесть расчитанны на не очень маленькие наборы. Но поскольку мы сортируем набор из &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов в наборы размера &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt;, то проблем не должно быть.&lt;br /&gt;
&lt;br /&gt;
Собственно алгоритм:&lt;br /&gt;
&lt;br /&gt;
Algorithm Sort(&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{0}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{t}&amp;lt;/tex&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt; это неконсервативное преимущество, &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;-ые это входящие целые числа в наборе, которые надо отсортировать, &amp;lt;tex&amp;gt;level&amp;lt;/tex&amp;gt; это уровень рекурсии.&lt;br /&gt;
&lt;br /&gt;
1) &amp;lt;tex&amp;gt;if level == 1&amp;lt;/tex&amp;gt; тогда изучить размер набора. Если&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25139</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25139"/>
				<updated>2012-06-12T00:00:51Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;br /&gt;
&lt;br /&gt;
Сложная часть алгоритма заключается в том, как поместить маленькие числа в набор, которому принадлежит соответствующее число, после предыдущих операций деления набора в нашем алгоритме. Предположим, что &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел уже поделены в &amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt; наборов. Мы можем использовать &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; битов чтобы сделать марки для каждого набора. Теперь хотелось бы использовать лемму шесть. Полный размер маркера для каждого контейнера должен быть &amp;lt;tex&amp;gt;logn/2&amp;lt;/tex&amp;gt;, и маркер использует &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, количество маркеров &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; в каждом контейнере должно быть не более &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt;. В дальнейшем т.к. &amp;lt;tex&amp;gt;g = logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. должны влезать в контейнер. Каждый контейнер содержит &amp;lt;tex&amp;gt;kloglognlogn&amp;lt;/tex&amp;gt; блоков, каждое м.ч. может содержать &amp;lt;tex&amp;gt;O(klogn/g) = O(kloge)&amp;lt;/tex&amp;gt; блоков. Заметим, что мы используем неконсервативное преимущество в &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; для использования леммы шесть. Поэтому мы предполагаем что &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; м.ч. в каждом из которых &amp;lt;tex&amp;gt;kloge&amp;lt;/tex&amp;gt; блоков битов числа упакованный в один контейнер. Для каждого м.ч. мы используем маркер из &amp;lt;tex&amp;gt;loge&amp;lt;/tex&amp;gt; бит, который показывает к какому набору он принадлежит. Предполагаем, что маркеры так же упакованы в контейнеры как и м.ч. Так как каждый контейнер для маркеров содержит &amp;lt;tex&amp;gt;logn/(2loge)&amp;lt;/tex&amp;gt; маркеров, то для каждого контейнера требуется &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Таким образом лемма шесть может быть применена для помещения м.ч. в наборы, которым они принадлежат. Так как используется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; контейнеров то время необходимое для помещения м.ч. в их наборы потребуется &amp;lt;tex&amp;gt;O((nloge)/logn)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что процесс помещения нестабилен, т.к. основан на алгоритме из леммы шесть.&lt;br /&gt;
&lt;br /&gt;
При таком помещении мы сразу сталкиваемся со следующей проблемой.&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25131</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25131"/>
				<updated>2012-06-11T23:14:28Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой. Пусть &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; это набор чисел, у которых наибольший блок находится в &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;. Тогда мы можем убрать убрать &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит (наибольший блок) из каждого числа из &amp;lt;tex&amp;gt;S'_{2}&amp;lt;/tex&amp;gt; из дальнейшего рассмотрения. Таким образом после первой стадии каждое число находится в наборе размера не большего половины размера начального набора или один из блоков в числе убран из дальнейшего рассмотрения. Так как в каждом числе только &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков, для каждого числа потребуется не более &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; стадий чтобы поместить его в набор половинного размера. За &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий все числа будут отсортированы. Так как на каждой стадии мы работаем с &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнерами, то игнорируя время, необходимое на упаковку м.ч. в контейнеры и помещение м.ч. в нужный набор, мы затратим &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; времени из-за &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt; стадий.&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	<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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25130</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%A5%D0%B0%D0%BD%D0%B0&amp;diff=25130"/>
				<updated>2012-06-11T22:58:23Z</updated>
		
		<summary type="html">&lt;p&gt;Da1s60: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка Хана (Yijie Han)''' {{---}} сложный алгоритм сортировки целых чисел со сложностью &amp;lt;tex&amp;gt;O(nloglog n)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} количество элементов для сортировки.&lt;br /&gt;
&lt;br /&gt;
Данная статья писалась на основе брошюры Хана, посвященной этой сортировке. Изложение материала в данной статье идет примерно в том же порядке, в каком она предоставлена в работе Хана.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Алгоритм построен на основе экспоненциального поискового дерева (далее {{---}} Э.П.дерево) Андерсона (Andersson's exponential search tree). Сортировка происходит за счет вставки целых чисел в Э.П.дерево.&lt;br /&gt;
&lt;br /&gt;
== Andersson's exponential search tree ==&lt;br /&gt;
Э.П.дерево с &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; листьями состоит из корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;n^e&amp;lt;/tex&amp;gt; (0&amp;lt;&amp;lt;tex&amp;gt;e&amp;lt;/tex&amp;gt;&amp;lt;1) Э.П.поддеревьев, в каждом из которых &amp;lt;tex&amp;gt;n^{1 - e}&amp;lt;/tex&amp;gt; листьев; каждое Э.П.поддерево является сыном корня &amp;lt;tex&amp;gt;r&amp;lt;/tex&amp;gt;. В этом дереве &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; уровней. При нарушении баланса дерева, необходимо балансирование, которое требует &amp;lt;tex&amp;gt;O(n \log\log n)&amp;lt;/tex&amp;gt; времени при &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; вставленных целых числах. Такое время достигается за счет вставки чисел группами, а не по одиночке, как изначально предлагает Андерссон.&lt;br /&gt;
&lt;br /&gt;
==Необходимая информация==&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def1. &lt;br /&gt;
|definition=&lt;br /&gt;
Контейнер {{---}} объект определенного типа, содержащий обрабатываемый элемент. Например __int32, __int64, и т.д.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def2. &lt;br /&gt;
|definition=&lt;br /&gt;
Алгоритм сортирующий &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества &amp;lt;tex&amp;gt;\{0, 1, \ldots, m - 1\}&amp;lt;/tex&amp;gt; называется консервативным, если длина контейнера (число бит в контейнере), является &amp;lt;tex&amp;gt;O(\log(m + n))&amp;lt;/tex&amp;gt;. Если длина больше, то алгоритм неконсервативный.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def3. &lt;br /&gt;
|definition=&lt;br /&gt;
Если мы сортируем целые числа из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} с длиной контейнера &amp;lt;tex&amp;gt;klog(m + n)&amp;lt;/tex&amp;gt; с &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt; &amp;gt;= 1, тогда мы сортируем с неконсервативным преимуществом &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=def4. &lt;br /&gt;
|definition=&lt;br /&gt;
Для множества &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; определим&lt;br /&gt;
min(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = min(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
max(&amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;) = max(&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;:&amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; принадлежит &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;)&lt;br /&gt;
Набор &amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt; если max(&amp;lt;tex&amp;gt;S1&amp;lt;/tex&amp;gt;) &amp;lt;= min(&amp;lt;tex&amp;gt;S2&amp;lt;/tex&amp;gt;)&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Уменьшение числа бит в числах==&lt;br /&gt;
Один из способов ускорить сортировку {{---}} уменьшить число бит в числе. Один из способов уменьшить число бит в числе {{---}} использовать деление пополам (эту идею впервые подал van Emde Boas). Деление пополам заключается в том, что количество оставшихся бит в числе уменьшается в 2 раза. Это быстрый способ, требующий &amp;lt;tex&amp;gt;O(m)&amp;lt;/tex&amp;gt; памяти. Для своего дерева Андерссон использует хеширование, что позволяет сократить количество памяти до &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Для того, чтобы еще ускорить алгоритм нам необходимо упаковать несколько чисел в один контейнер, чтобы затем за константное количество шагов произвести хэширование для всех чисел хранимых в контейнере. Для этого используется хэш функция для хэширования &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; за константное время, без коллизий. Для этого используется хэш модифицированная функция авторства: Dierzfelbinger и Raman.&lt;br /&gt;
&lt;br /&gt;
Алгоритм: Пусть целое число &amp;lt;tex&amp;gt;b &amp;gt;= 0&amp;lt;/tex&amp;gt; и пусть &amp;lt;tex&amp;gt;U = \{0, \ldots, 2^b - 1\}&amp;lt;/tex&amp;gt;. Класс &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; хэш функций из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;\{0, \ldots, 2^s - 1\}&amp;lt;/tex&amp;gt; определен как &amp;lt;tex&amp;gt;H_{b,s} = \{h_{a} \mid 0 &amp;lt; a &amp;lt; 2^b, a \equiv 1 (\mod 2)\}&amp;lt;/tex&amp;gt; и для всех &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt;U: h_{a}(x) = (ax \mod 2^b) div 2^{b - s}&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм базируется на следующей лемме:&lt;br /&gt;
&lt;br /&gt;
Номер один.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma1. &lt;br /&gt;
|statement=&lt;br /&gt;
Даны целые числа &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; &amp;gt;= 0 и &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; является подмножеством {0, ..., &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt; - 1}, содержащим &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; элементов, и &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt; &amp;gt;= &amp;lt;tex&amp;gt;2^{-s + 1}&amp;lt;/tex&amp;gt;С&amp;lt;tex&amp;gt;^k_{n}&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; принадлежащая &amp;lt;tex&amp;gt;H_{b,s}&amp;lt;/tex&amp;gt; может быть выбрана за время &amp;lt;tex&amp;gt;O(bn^2)&amp;lt;/tex&amp;gt; так, что количество коллизий &amp;lt;tex&amp;gt;coll(h_{a}, T) &amp;lt;= t&amp;lt;/tex&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Взяв &amp;lt;tex&amp;gt;s = 2logn&amp;lt;/tex&amp;gt; мы получим хэш функцию &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; которая захэширует &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел из &amp;lt;tex&amp;gt;U&amp;lt;/tex&amp;gt; в таблицу размера &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt; без коллизий. Очевидно, что &amp;lt;tex&amp;gt;h_{a}(x)&amp;lt;/tex&amp;gt; может быть посчитана для любого &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; за константное время. Если мы упакуем несколько чисел в один контейнер так, что они разделены несколькими битами нулей, мы спокойно сможем применить &amp;lt;tex&amp;gt;h_{a}&amp;lt;/tex&amp;gt; ко всему контейнеру, а в результате все хэш значения для всех чисел в контейере были посчитаны. Заметим, что это возможно только потому, что в вычисление хэш знчения вовлечены только (mod &amp;lt;tex&amp;gt;2^b&amp;lt;/tex&amp;gt;) и (div &amp;lt;tex&amp;gt;2^{b - s}&amp;lt;/tex&amp;gt;). &lt;br /&gt;
&lt;br /&gt;
Такая хэш функция может быть найдена за &amp;lt;tex&amp;gt;O(n^3)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что несмотря на размер таблицы &amp;lt;tex&amp;gt;O(n^2)&amp;lt;/tex&amp;gt;, потребность в памяти не превышает &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; потому, что хэширование используется только для уменьшения количества бит в числе.&lt;br /&gt;
&lt;br /&gt;
==Signature sorting==&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;logm&amp;lt;/tex&amp;gt; бит. Мы рассматриваем, что в каждом числе есть &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов, в каждом из которых &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит. Теперь мы применяем хэширование ко всем сегментам и получаем &amp;lt;tex&amp;gt;2hlogn&amp;lt;/tex&amp;gt; бит хэшированных значений для каждого числа. После сортировки на хэшированных значениях для всех начальных чисел начальная задача по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; бит в каждом стала задачей по сортировке &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел по &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит в каждом.&lt;br /&gt;
&lt;br /&gt;
Так же, рассмотрим проблему последующего разделения. Пусть &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; {{---}} множество чисeл. Мы хотим разделить &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;p + 1&amp;lt;/tex&amp;gt; наборов таких, что: &amp;lt;tex&amp;gt;S_{0}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; &amp;lt; {&amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt;} &amp;lt; ... &amp;lt; {&amp;lt;tex&amp;gt;a_{p}&amp;lt;/tex&amp;gt;} &amp;lt; &amp;lt;tex&amp;gt;S_{p}&amp;lt;/tex&amp;gt;. Т.к. мы используем signature sorting, до того как делать вышеописанное разделение, мы поделим биты в &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов и возьмем некоторые из них. Мы так же поделим биты для каждого числа из &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt; и оставим только один в каждом числе. По существу для каждого &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; мы возьмем все &amp;lt;tex&amp;gt;h&amp;lt;/tex&amp;gt; сегментов. Если соответствующие сегменты &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{j}&amp;lt;/tex&amp;gt; совпадают, то нам понадобится только один. Сегменты, которые мы берем для числа в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;, {{---}} сегмент, который выделяется из &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;. Таким образом мы преобразуем начальную задачу о разделении &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит в несколько задач на разделение с числами в &amp;lt;tex&amp;gt;log(m/h)&amp;lt;/tex&amp;gt; бит.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; = 3, &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; = 5, &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; = 7, &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; = 10, S = {1, 4, 6, 8, 9, 13, 14}.&lt;br /&gt;
&lt;br /&gt;
Мы разделим числа на 2 сегмента. Для &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt; получим верхний сегмент 0, нижний 3; &amp;lt;tex&amp;gt;a_{2}&amp;lt;/tex&amp;gt; верхний 1, нижний 1; &amp;lt;tex&amp;gt;a_{3}&amp;lt;/tex&amp;gt; верхний 1, нижний 3; &amp;lt;tex&amp;gt;a_{4}&amp;lt;/tex&amp;gt; верхний 2, нижний 2. Для элементов из S получим: для 1: нижний 1 т.к. он выделяется из нижнего сегмента &amp;lt;tex&amp;gt;a_{1}&amp;lt;/tex&amp;gt;; для 4 нижний 0; для 8 нижний 0; для 9 нижний 1; для 13 верхний 3; для 14 верхний 3. Теперь все верхние сегменты, нижние сегменты 1 и 3, нижние сегменты 4, 5, 6, 7, нижние сегменты  8, 9, 10 формируют 4 новые задачи на разделение.&lt;br /&gt;
&lt;br /&gt;
==Сортировка на маленьких целых==&lt;br /&gt;
Для лучшего понимания действия алгоритма и материала, изложенного в данной статье, в целом, ниже представлены несколько полезных лемм. &lt;br /&gt;
&lt;br /&gt;
Номер два.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma2. &lt;br /&gt;
|statement=&lt;br /&gt;
&amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел можно отсортировать в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt;, ..., &amp;lt;tex&amp;gt;S_{\sqrt{n}}&amp;lt;/tex&amp;gt; таким образом, что в каждом наборе &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; чисел и &amp;lt;tex&amp;gt;S_{i}&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;S_{j}&amp;lt;/tex&amp;gt; при &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; &amp;lt; &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt;, за время &amp;lt;tex&amp;gt;O(nloglogn/logk)&amp;lt;/tex&amp;gt; и место &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; с не консервативным преимуществом &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;&lt;br /&gt;
|proof=&lt;br /&gt;
Доказательство данной леммы будет приведено далее в тексте статьи.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер три.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma3. &lt;br /&gt;
|statement=&lt;br /&gt;
Выбор &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ого наибольшего числа среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел упакованных в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров может быть сделана за &amp;lt;tex&amp;gt;O(nlogg/g)&amp;lt;/tex&amp;gt; время и с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места. Конкретно медиана может быть так найдена.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как мы можем делать попарное сравнение &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел в одном контейнере с &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; числами в другом и извлекать большие числа из одного контейнера и меньшие из другого за константное время, мы можем упаковать медианы из первого, второго, ..., &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-ого чисел из 5 контейнеров в один контейнер за константное время. Таким образом набор &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;  из медиан теперь содержится в &amp;lt;tex&amp;gt;n/(5g)&amp;lt;/tex&amp;gt; контейнерах. Рекурсивно находим медиану &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt;S&amp;lt;/tex&amp;gt;. Используя &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; уберем хотя бы &amp;lt;tex&amp;gt;n/4&amp;lt;/tex&amp;gt; чисел среди &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Затем упакуем оставшиеся из &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;3n/4g&amp;lt;/tex&amp;gt; контейнеров и затем продолжим рекурсию.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Номер четыре.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma4.&lt;br /&gt;
|statement=&lt;br /&gt;
Если &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; целых чисел, в сумме использующие &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы за время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
|proof=&lt;br /&gt;
Так как используется только &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит в каждом контейнере для хранения &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, мы можем использовать bucket sorting чтобы отсортировать все контейнеры. представляя каждый как число, что занимает &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени и места. Потому, что мы используем &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит на контейнер нам понадобится &amp;lt;tex&amp;gt;\sqrt {n}&amp;lt;/tex&amp;gt; шаблонов для всех контейнеров. Затем поместим &amp;lt;tex&amp;gt;g &amp;lt; (logn)/2&amp;lt;/tex&amp;gt; контейнеров с одинаковым шаблоном в одну группу. Для каждого шаблона останется не более &amp;lt;tex&amp;gt;g - 1&amp;lt;/tex&amp;gt; контейнеров которые не смогут образовать группу. Поэтому не более &amp;lt;tex&amp;gt;\sqrt{n}(g - 1)&amp;lt;/tex&amp;gt; контейнеров не смогут сформировать группу. Для каждой группы мы помещаем &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-е число во всех &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерах в один. Таким образом мы берем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов и получаем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt;-целых векторов где &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый вектор содержит &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ое число из входящего вектора. Эта транспозиция может быть сделана за время &amp;lt;tex&amp;gt;O(glogg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(g)&amp;lt;/tex&amp;gt; места. Для всех групп это занимает время &amp;lt;tex&amp;gt;O((n/g)logg)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
&lt;br /&gt;
Для контейнеров вне групп (которых &amp;lt;tex&amp;gt;\sqrt(n)(g - 1)&amp;lt;/tex&amp;gt; штук) мы просто разберем и соберем заново контейнеры. На это потребуется не более &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места и времени. После всего этого мы используем bucket sorting вновь для сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; контейнеров. таким образом мы отсортируем все числа.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что когда &amp;lt;tex&amp;gt;g = O(logn)&amp;lt;/tex&amp;gt; мы сортируем &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнеров за время &amp;lt;tex&amp;gt;O((n/g)loglogn)&amp;lt;/tex&amp;gt;, с использованием O(n/g) места. Выгода очевидна.&lt;br /&gt;
&lt;br /&gt;
Лемма пять.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma5.&lt;br /&gt;
|statement=&lt;br /&gt;
Если принять, что каждый контейнер содержит &amp;lt;tex&amp;gt;logm &amp;gt; logn&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер. Если каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер таким же образом&amp;lt;tex&amp;gt;^*&amp;lt;/tex&amp;gt;, что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по их маркерам за время &amp;lt;tex&amp;gt;O((nloglogn)/g)&amp;lt;/tex&amp;gt; с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; места.&lt;br /&gt;
(*): если число &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упаковано как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ое число в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для чисел, тогда маркер для &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; упакован как &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;-ый маркер в &amp;lt;tex&amp;gt;t&amp;lt;/tex&amp;gt;-ом контейнере для маркеров.&lt;br /&gt;
|proof=&lt;br /&gt;
Контейнеры для маркеров могут быть отсортированы с помощью bucket sort потому, что каждый контейнер использует &amp;lt;tex&amp;gt;(logn)/2&amp;lt;/tex&amp;gt; бит. Сортировка сгруппирует контейнеры для чисел как в четвертой лемме. Мы можем переместить каждую группу контейнеров для чисел.&lt;br /&gt;
}}&lt;br /&gt;
Заметим, что сортирующие алгоритмы в четвертой и пятой леммах нестабильные. Хотя на их основе можно построить стабильные алгоритмы используя известный метод добавления адресных битов к каждому входящему числу.&lt;br /&gt;
&lt;br /&gt;
Если у нас длина контейнеров больше, сортировка может быть ускорена, как показано в следующей лемме.&lt;br /&gt;
&lt;br /&gt;
Лемма шесть.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|id=lemma6.&lt;br /&gt;
|statement=&lt;br /&gt;
предположим, что каждый контейнер содержит &amp;lt;tex&amp;gt;logmloglogn &amp;gt; logn&amp;lt;/tex&amp;gt; бит, что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; чисел, в каждом из которых &amp;lt;tex&amp;gt;(logm)/g&amp;lt;/tex&amp;gt; бит, упакованы в один контейнер, что каждое число имеет маркер, содержащий &amp;lt;tex&amp;gt;(logn)/(2g)&amp;lt;/tex&amp;gt; бит, и что &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; маркеров упакованы в один контейнер тем же образом что и числа, тогда &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; чисел в &amp;lt;tex&amp;gt;n/g&amp;lt;/tex&amp;gt; контейнерах могут быть отсортированы по своим маркерам за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, с использованием &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
|proof=&lt;br /&gt;
Заметим, что несмотря на то, что длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; бит всего &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для хранения упакованных чисел. Так же как в леммах четыре и пять мы сортируем контейнеры упакованных маркеров с помощью bucket sort. Для того, чтобы перемещать контейнеры чисел мы помещаем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; вместо &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров чисел в одну группу. Для транспозиции чисел в группе содержащей &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров мы сначала упаковываем &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров упаковывая &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; контейнеров в один. Далее мы делаем транспозицию над &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнерами. Таким образом перемещение занимает всего &amp;lt;tex&amp;gt;O(gloglogn)&amp;lt;/tex&amp;gt; времени для каждой группы и &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt; времени для всех чисел. После завершения транспозиции, мы далее распаковываем &amp;lt;tex&amp;gt;g&amp;lt;/tex&amp;gt; контейнеров в &amp;lt;tex&amp;gt;gloglogn&amp;lt;/tex&amp;gt; контейнеров.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что если длина контейнера &amp;lt;tex&amp;gt;logmloglogn&amp;lt;/tex&amp;gt; и только &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит используется для упаковки &amp;lt;tex&amp;gt;g &amp;lt;= logn&amp;lt;/tex&amp;gt; чисел в один контейнер, тогда выбор в лемме три может быть сделан за время и место &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;, потому, что упаковка в доказатльстве леммы три теперь может быть сделана за время &amp;lt;tex&amp;gt;O(n/g)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сортировка &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов==&lt;br /&gt;
Постановка задачи и решение некоторых проблем:&lt;br /&gt;
&lt;br /&gt;
Рассмотрим проблему сортировки &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; целых чисел из множества {0, 1, ..., &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; - 1} в &amp;lt;tex&amp;gt;\sqrt{n}&amp;lt;/tex&amp;gt; наборов как во второй лемме. Мы предполагаем, что в каждом контейнере &amp;lt;tex&amp;gt;kloglognlogm&amp;lt;/tex&amp;gt; бит и хранит число в &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит. Поэтому неконсервативное преимущество &amp;lt;tex&amp;gt;kloglogn&amp;lt;/tex&amp;gt;. Мы так же предполагаем, что &amp;lt;tex&amp;gt;logm &amp;gt;= lognloglogn&amp;lt;/tex&amp;gt;. Иначе мы можем использовать radix sort для сортировки за время &amp;lt;tex&amp;gt;O(nloglogn)&amp;lt;/tex&amp;gt; и линейную память. Мы делим &amp;lt;tex&amp;gt;logm&amp;lt;/tex&amp;gt; бит, используемых для представления каждого числа, в &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; блоков. Таким образом каждый блок содержит как минимум &amp;lt;tex&amp;gt;loglogn&amp;lt;/tex&amp;gt; бит. &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;-ый блок содержит с &amp;lt;tex&amp;gt;ilogm/logn&amp;lt;/tex&amp;gt;-ого по &amp;lt;tex&amp;gt;((i + 1)logm/logn - 1)&amp;lt;/tex&amp;gt;-ый биты. Биты считаются с наименьшего бита начиная с нуля. Теперь у нас имеется &amp;lt;tex&amp;gt;2logn&amp;lt;/tex&amp;gt;-уровневый алгоритм, который работает следующим образом:&lt;br /&gt;
&lt;br /&gt;
На каждой стадии мы работаем с одним блоком бит. Назовем эти блоки маленькими числами (далее м.ч.) потому, что каждое м.ч. теперь содержит только &amp;lt;tex&amp;gt;logm/logn&amp;lt;/tex&amp;gt; бит. Каждое число представлено и соотносится с м.ч., над которым мы работаем в данный момент. Положим, что нулевая стадия работает с самыми большим блоком (блок номер &amp;lt;tex&amp;gt;logn - 1&amp;lt;/tex&amp;gt;). Предполагаем, что биты этих м.ч. упакованы в &amp;lt;tex&amp;gt;n/logn&amp;lt;/tex&amp;gt; контейнеров с &amp;lt;tex&amp;gt;logn&amp;lt;/tex&amp;gt; м.ч. упакованных в один контейнер. Мы пренебрегаем временем, потраченным на на эту упаковку, считая что она бесплатна. По третьей лемме мы можем найти медиану этих &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; м.ч. за время и память &amp;lt;tex&amp;gt;O(n/logn)&amp;lt;/tex&amp;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;S_{1}&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt;. &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; содержит м.ч. которые меньше &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; содержит м.ч. равные &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;, &amp;lt;tex&amp;gt;S_{3}&amp;lt;/tex&amp;gt; содержит м.ч. большие &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt;. Так же мощность &amp;lt;tex&amp;gt;S_{1}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;S_{3} &amp;lt;/tex&amp;gt;&amp;lt;= &amp;lt;tex&amp;gt;n/2&amp;lt;/tex&amp;gt;. Мощность &amp;lt;tex&amp;gt;S_{2}&amp;lt;/tex&amp;gt; может быть любой.&lt;/div&gt;</summary>
		<author><name>Da1s60</name></author>	</entry>

	</feed>