Цифровая сортировка — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Алгоритм)
(Псевдокод)
Строка 22: Строка 22:
  
 
== Псевдокод ==
 
== Псевдокод ==
В качестве примера рассмотрим сортировку чисел. Как говорилось выше, в такой ситуации в качестве стабильной сортировки применяют сортировку подсчетом, так как обычно количество различных значений разрядов не превосходит количества сортируемых элементов. Ниже приведен псевдокод цифровой сортировки, которой подается массив <tex> A </tex> <tex> m </tex>-разрядных чисел размера <tex> n </tex>. Сам по себе алгоритм представляет собой цикл по номеру разряда, на каждой итерации которого элементы массива <tex> A </tex> размещаются в нужном порядке во вспомогательном массиве <tex> B </tex>. Для подсчета количества объектов, <tex> i </tex>-ый разряд которых одинаковый, а затем и для определения положения объектов в массиве <tex> B </tex> используется вспомогательный массив <tex> C </tex>. Функция <tex> digit(x, i) </tex> возвращает <tex> i </tex>-ый разряд числа <tex> x </tex>. Так же считаем, что значения разрядов меньше <tex> k </tex>.
+
В качестве примера рассмотрим сортировку чисел. Как говорилось выше, в такой ситуации в качестве стабильной сортировки применяют сортировку подсчетом, так как обычно количество различных значений разрядов не превосходит количества сортируемых элементов. Ниже приведен псевдокод цифровой сортировки, которой подается массив <tex> A </tex> <tex> m </tex>-разрядных чисел размера <tex> n </tex>. Сам по себе алгоритм представляет собой цикл по номеру разряда, на каждой итерации которого элементы массива <tex> A </tex> размещаются в нужном порядке во вспомогательном массиве <tex> B </tex>. Для подсчета количества объектов, <tex> i </tex>-ый разряд которых одинаковый, а затем и для определения положения объектов в массиве <tex> B </tex> используется вспомогательный массив <tex> C </tex>. Функция <tex> digit(x, i) </tex> возвращает <tex> i </tex>-ый разряд числа <tex> x </tex>. Также считаем, что значения разрядов меньше <tex> k </tex>.
 
   radixSort(A)
 
   radixSort(A)
       for i = 1 to m                                   
+
       '''for''' i = 1 '''to''' m                                   
           for j = 0 to k - 1                               
+
           '''for''' j = 0 '''to''' k - 1                               
 
               C[j] = 0;                                   
 
               C[j] = 0;                                   
           for j = 0 to n - 1
+
           '''for''' j = 0 '''to''' n - 1
 
               C[digit(A[j], i)] = C[digit(A[j], i)] + 1;  
 
               C[digit(A[j], i)] = C[digit(A[j], i)] + 1;  
           for j = 1 to k - 1
+
           '''for''' j = 1 '''to''' k - 1
 
               C[j] = C[j] + C[j - 1];
 
               C[j] = C[j] + C[j - 1];
           for j = n - 1 to 0                             
+
           '''for''' j = n - 1 '''to''' 0                             
 
               B[C[digit(A[j], i)]] = A[j];               
 
               B[C[digit(A[j], i)]] = A[j];               
 
               C[digit(A[j], i)] = C[digit(A[j], i)] - 1;
 
               C[digit(A[j], i)] = C[digit(A[j], i)] - 1;

Версия 14:27, 7 июня 2012

Цифровая сортировка — один из алгоритмов сортировки, использующих внутреннюю структуру сортируемых объектов.

Алгоритм

Пример цифровой сортировки трехзначных чисел

При цифровой сортировке данные разбиваются на "разряды", после чего они сортируются какой-либо устойчивой сортировкой по каждому разряду, в порядке от младшего разряда к старшему. Заметим, что лексикографический порядок сортировки разрядов должен совпадать с требуемым от самой цифровой сортировки. Например, если объекты сортируются по невозрастанию, то при сортировки по [math] i [/math]-ому разряду объект с меньшим [math] i [/math]-ым разрядом должен идти раньше, чем объект, у которого данный разряд больше. В этом нетрудно убедиться, если на вход алгоритму подать объекты, состоящие из одного разряда.

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

  • Для чисел уже существует понятие разряда, поэтому разбивать будем именно по ним. Конечно, в разных системах счисления разряды одного и того же числа отличаются, поэтому перед тем как разбивать число, представим его в удобной для нас системе счисления.
  • Так как строки представляют из себя массивы символов, то в качестве разряда можно брать отдельные символы, сравнение которых обычно происходит по соответствующим им кодам из таблицы кодировок. Для такого разбиения самый младший разряд — последний символ строки.

Для вышеперечисленных объектов наиболее часто в качестве устойчивой сортировки применяют сортировку подсчетом.

Корректность алгоритма

Докажем, что данный алгоритм работает верно, используя метод математической индукции по номеру разряда. Пусть [math] n [/math] — количество разрядов в сортируемых объектах.

База: [math] n = 1 [/math]. Очевидно, что алгоритм работает верно, потому что в таком случае мы просто сортируем младшие разряды какой-то заранее выбранной стабильной сортировкой.

Переход: Пусть для [math] n = k [/math] алгоритм правильно отсортировал элементы по [math] k [/math] младшим разрядам. Покажем, что в таком случае, при сортировке по [math] (k + 1) [/math]-ому разряду, объекты также будут отсортированы в правильном порядке.

Вспомогательная сортировка разобьет все объекты на группы, в которых [math] (k + 1) [/math]-ый разряд объектов одинаковый. Рассмотрим такие группы. Для сортировки по отдельным разрядам мы используем стабильную сортировку, следовательно порядок объектов с одинаковым [math] (k + 1) [/math]-ым разрядом не изменился. Но по предположению индукции по предыдущим [math] k [/math] разрядам объекты были отсортированы правильно, и поэтому в каждой такой группе объекты будут отсортированы верно. Также верно, что сами группы находятся в правильном относительно друг друга порядке, а, следовательно, и все элементы отсортированы правильно по [math] (k + 1) [/math]-ым младшим разрядам.

Псевдокод

В качестве примера рассмотрим сортировку чисел. Как говорилось выше, в такой ситуации в качестве стабильной сортировки применяют сортировку подсчетом, так как обычно количество различных значений разрядов не превосходит количества сортируемых элементов. Ниже приведен псевдокод цифровой сортировки, которой подается массив [math] A [/math] [math] m [/math]-разрядных чисел размера [math] n [/math]. Сам по себе алгоритм представляет собой цикл по номеру разряда, на каждой итерации которого элементы массива [math] A [/math] размещаются в нужном порядке во вспомогательном массиве [math] B [/math]. Для подсчета количества объектов, [math] i [/math]-ый разряд которых одинаковый, а затем и для определения положения объектов в массиве [math] B [/math] используется вспомогательный массив [math] C [/math]. Функция [math] digit(x, i) [/math] возвращает [math] i [/math]-ый разряд числа [math] x [/math]. Также считаем, что значения разрядов меньше [math] k [/math].

 radixSort(A)
     for i = 1 to m                                  
         for j = 0 to k - 1                              
             C[j] = 0;                                  
         for j = 0 to n - 1
             C[digit(A[j], i)] = C[digit(A[j], i)] + 1; 
         for j = 1 to k - 1
             C[j] = C[j] + C[j - 1];
         for j = n - 1 to 0                             
             B[C[digit(A[j], i)]] = A[j];               
             C[digit(A[j], i)] = C[digit(A[j], i)] - 1;
         A = B;

Сложность

Пусть [math] m [/math] — количество разрядов, [math] n [/math] — количество объектов, которые нужно отсортировать, [math] T(n) [/math] — время работы устойчивой сортировки. Цифровая сортировка выполняет [math] k [/math] итераций, на каждой из которой выполняется устойчивая сортировка и не более [math] O(1) [/math] других операций. Следовательно время работы цифровой сортировки — [math] O(k \cdot T(n)) [/math].

Рассмотрим отдельно случай сортировки чисел. Пусть в качестве аргумента сортировке передается массив, в котором содержатся [math] n [/math] [math] m [/math]-значных чисел, и каждая цифра может принимать значения от [math] 0 [/math] до [math] k - 1 [/math]. Тогда цифровая сортировка позволяет отсортировать данный массив за время [math] O(m \cdot (n + k)) [/math], если устойчивая сортировка имеет время работы [math] O(n + k) [/math]. Если [math] k [/math] небольшое, то оптимально выбирать в качестве устойчивой сортировки сортировку подсчетом.

Если количество разрядов — константа, а [math] k = O(n) [/math], то сложность цифровой сортировки составляет [math] O(n) [/math], то есть она линейно зависит от количества сортируемых чисел.

Литература

  • Дональд Кнут Искусство программирования, том 3. Сортировка и поиск
  • Кормен, Т., Лейзерсон, Ч., Ривест, Р., Штайн, К. Алгоритмы: построение и анализ

Ссылки