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

Материал из Викиконспекты
Перейти к: навигация, поиск
м (rollbackEdits.php mass rollback)
 
(не показаны 3 промежуточные версии 2 участников)
Строка 18: Строка 18:
 
     '''if''' array.length < 2 '''or''' minElement == maxElement
 
     '''if''' array.length < 2 '''or''' minElement == maxElement
 
         '''return''' array;
 
         '''return''' array;
 +
    range = maxElement - minElement
 
     '''for''' i = 0  '''to''' array.length - 1   
 
     '''for''' i = 0  '''to''' array.length - 1   
 
         index = int(array[i] * numBuckets / range)
 
         index = int(array[i] * numBuckets / range)
 
         добавим array[i] в конец buckets[index]
 
         добавим array[i] в конец buckets[index]
         bucketsMinimum[i] = minimum(buckets[index], array[i])
+
         minBucktes[index] = '''minimum'''(buckets[index], array[i])
         bucketsMaximum[i] = maximum(buckets[index], array[i])
+
         maxBuckets[index] = '''maximum'''(buckets[index], array[i])
 
     '''for''' i = 0 '''to''' numBuckets - 1
 
     '''for''' i = 0 '''to''' numBuckets - 1
 
         buckets[i] = bucketSort(buckets[i], minBucktes[i], maxBuckets[i])
 
         buckets[i] = bucketSort(buckets[i], minBucktes[i], maxBuckets[i])
Строка 28: Строка 29:
 
         '''for''' k = 0 '''to''' buckets[i].length - 1
 
         '''for''' k = 0 '''to''' buckets[i].length - 1
 
             добавим buckets[i][k] в конец answer
 
             добавим buckets[i][k] в конец answer
     '''return''' answer  
+
     '''return''' answer
 +
 
 
==== Нерекурсивная реализация ====
 
==== Нерекурсивная реализация ====
 
  '''double[]''' bucketSort('''double[]''' array)  
 
  '''double[]''' bucketSort('''double[]''' array)  
Строка 36: Строка 38:
 
         minElement = '''minimum'''(minElement, array[i])
 
         minElement = '''minimum'''(minElement, array[i])
 
         maxElement = '''maximum'''(maxElement, array[i])  
 
         maxElement = '''maximum'''(maxElement, array[i])  
 +
    range = maxElement - minElement
 
     '''for''' i = 0  '''to''' array.length - 1   
 
     '''for''' i = 0  '''to''' array.length - 1   
 
         index = int(array[i] * numBuckets / range)
 
         index = int(array[i] * numBuckets / range)
Строка 44: Строка 47:
 
         '''for''' k = 0 '''to''' buckets[i].length - 1
 
         '''for''' k = 0 '''to''' buckets[i].length - 1
 
             добавим buckets[i][k] в конец answer
 
             добавим buckets[i][k] в конец answer
     '''return''' answer  
+
     '''return''' answer
  
 
==Асимптотика==
 
==Асимптотика==

Текущая версия на 19:15, 4 сентября 2022

Пример работы рекурсивного Bucketsort.

Карманная сортировка (англ. Bucket sort) — алгоритм сортировки, основанный на предположении о равномерном распределении входных данных.

Алгоритм сортировки

Принцип работы

Для карманной сортировки нужно разбить элементы массива входных данных на [math]k[/math] блоков (карманов, корзин). Далее каждый из таких блоков сортируется либо другой сортировкой, либо рекурсивно тем же методом разбиения. После сортировок внутри каждых блоков данные записываются в массив в порядке разбиения на блоки. При этом нужно учитывать, что данная сортировка работает только в том случае, если разбиение на блоки производится таким образом, чтобы элементы каждого следующего блока были больше предыдущего.

Карманная сортировка сильно деградирует при большом количестве мало отличных элементов (большинство элементов попадёт в одну корзину). Поэтому такой тип сортировки использовать, когда велика вероятность того, что числа редко повторяются (например, последовательность случайных чисел).

Реализация

Существует несколько разных реализаций карманной сортировки.

Рассмотрим рекурсивную и нерекурсивную реализации.

Рекурсивный bucket sort

Рассмотрим код работы рекурсивной реализации карманной сортировки.

На вход подаются вещественные числа.

double[] bucketSort (double[] array, double minElement, double maxElement) 
   if array.length < 2 or minElement == maxElement
       return array;
   range = maxElement - minElement
   for i = 0  to array.length - 1  
       index = int(array[i] * numBuckets / range)
       добавим array[i] в конец buckets[index]
       minBucktes[index] = minimum(buckets[index], array[i])
       maxBuckets[index] = maximum(buckets[index], array[i])
   for i = 0 to numBuckets - 1
       buckets[i] = bucketSort(buckets[i], minBucktes[i], maxBuckets[i])
   for i = 0 to numBuckets - 1
       for k = 0 to buckets[i].length - 1
           добавим buckets[i][k] в конец answer
   return answer

Нерекурсивная реализация

double[] bucketSort(double[] array) 
   minElement = Infinum
   maxElement = -Infinum
   for i = 0 to array.length - 1
       minElement = minimum(minElement, array[i])
       maxElement = maximum(maxElement, array[i]) 
   range = maxElement - minElement
   for i = 0  to array.length - 1  
       index = int(array[i] * numBuckets / range)
       добавим array[i] в конец buckets[index]
   for i = 0 to numBuckets - 1
       buckets[i] = sort(buckets[i])
   for i = 0 to numBuckets - 1
       for k = 0 to buckets[i].length - 1
           добавим buckets[i][k] в конец answer
   return answer

Асимптотика

Пусть [math]n[/math] — количество элементов в массиве, [math]k[/math] — количество блоков для разбиения.

[math] n_i [/math] — случайная величина, обозначающая количество элементов попавших в [math] i [/math]-ый карман.

[math] T(n) = \Theta(n) + \sum\limits_{i = 1}^k O(n_i[/math] [math] \log n_i) + \Theta(k)[/math], где [math] T(n) [/math] время работы алгоритма карманной сортировки.

[math] E[n_i] = \dfrac {n}{k} [/math]

То есть, если [math] n \sim k \Rightarrow E[T(n)] = \Theta(n) [/math]

Если, [math] n = o(k) \Rightarrow E[T(n)] = \Theta(k)[/math]

Из приведенных выше формул, видно, что в среднем "карманная сортировка" работает за линейное время.

Источники информации