Рубрики
Без рубрики

Сортировка ведра в Python

В этом уроке мы погрузимся в теорию и реализацию Bucket Sort в Python. Мы также будем исследовать его временную сложность.

Автор оригинала: Muhammad Junaid Khalid.

Сортировка ведра в Python

Вступление

В этом уроке мы погрузимся в теорию и реализацию Bucket Sort в Python.

Сортировка по ведрам-это алгоритм сравнения , который присваивает элементы списка, которые мы хотим отсортировать в Ведрах или Бункерах . Содержимое этих ведер затем сортируется, как правило, с помощью другого алгоритма. После сортировки содержимое ведер добавляется, образуя отсортированную коллекцию.

Сортировку по ведрам можно рассматривать как подход scatter-order-gather к сортировке списка из-за того, что элементы сначала разбросаны в ведрах, упорядочены внутри них и, наконец, собраны в новый, отсортированный список.

Мы реализуем сортировку по ведрам в Python и проанализируем ее временную сложность.

Как работает Сортировка по Ведрам?

Прежде чем перейти к его точной реализации, давайте пройдемся по шагам алгоритма:

  1. Составьте список пустых ведер. Ведро инициализируется для каждого элемента в массиве.
  2. Выполните итерацию по списку сегментов и вставьте элементы из массива. Место вставки каждого элемента зависит от входного списка и самого большого элемента в нем. Мы можем получить 0..n элементов в каждом ведре. Это будет подробно рассмотрено в визуальном представлении алгоритма.
  3. Сортируйте каждое непустое ведро. Вы можете сделать это с помощью любого алгоритма сортировки. Поскольку мы работаем с небольшим набором данных, в каждом ведре не будет много элементов, поэтому Сортировка вставки творит для нас здесь чудеса.
  4. Посетите ведра по порядку. Как только содержимое каждого ведра будет отсортировано, при объединении они дадут список, в котором элементы будут расположены на основе ваших критериев.

Посетите ведра по порядку. Как только содержимое каждого ведра будет отсортировано, при объединении они дадут список, в котором элементы будут расположены на основе ваших критериев.

Посетите ведра по порядку. Как только содержимое каждого ведра будет отсортировано, при объединении они дадут список, в котором элементы будут расположены на основе ваших критериев.

Самый большой элемент-это 1.2 , а длина списка равна 6 . Используя эти два параметра, мы определим оптимальный размер каждого ведра. Мы получим это число, разделив самый большой элемент на длину списка. В нашем случае это 1.2/6 а именно 0.2 .

Разделив значение элемента на этот размер , мы получим индекс для соответствующего ведра каждого элемента.

Теперь мы создадим пустые ведра. У нас будет столько же ведер, сколько элементов в нашем списке:

визуализация сортировки ведра

Мы вставим элементы в соответствующие ведра. Принимая во внимание первый элемент – 1.2/0.2 , индекс его соответствующего ведра равен 6 . Если этот результат больше или равен длине списка, мы просто вычтем 1 и это прекрасно впишется в список. Это происходит только с самым большим числом, так как мы получили размер , разделив самый большой элемент на длину.

Мы поместим этот элемент в ведро с индексом 5 :

визуализация сортировки ведра

Аналогично, следующий элемент будет проиндексирован на 0.22/0.2.1 . Так как это десятичное число, то мы его наполним. Это округляется до 1 , и наш элемент помещается во второе ведро:

визуализация сортировки ведра

Этот процесс повторяется до тех пор, пока мы не поместим последний элемент в соответствующее ведро. Наши ведра теперь выглядят примерно так::

визуализация сортировки ведра

Теперь мы отсортируем содержимое каждого непустого ведра. Мы будем использовать сортировку вставки, так как она непобедима с такими маленькими списками, как этот. После сортировки вставки ведра выглядят следующим образом:

визуализация сортировки ведра

Теперь это просто вопрос обхода непустых ведер и объединения элементов в список. Они рассортированы и готовы к отправке:

визуализация сортировки ведра

Реализация сортировки ведра в Python

С этим покончено, давайте продолжим и реализуем алгоритм на Python. Давайте начнем с самой функции bucket_sort() :

def bucket_sort(input_list):
    # Find maximum value in the list and use length of the list to determine which value in the list goes into which bucket 
    max_value = max(input_list)
    size = max_value/len(input_list)

    # Create n empty buckets where n is equal to the length of the input list
    buckets_list= []
    for x in range(len(input_list)):
        buckets_list.append([]) 

    # Put list elements into different buckets based on the size
    for i in range(len(input_list)):
        j = int (input_list[i] / size)
        if j != len (input_list):
            buckets_list[j].append(input_list[i])
        else:
            buckets_list[len(input_list) - 1].append(input_list[i])

    # Sort elements within the buckets using Insertion Sort
    for z in range(len(input_list)):
        insertion_sort(buckets_list[z])
            
    # Concatenate buckets with sorted elements into a single list
    final_output = []
    for x in range(len (input_list)):
        final_output = final_output + buckets_list[x]
    return final_output

Реализация довольно проста. Мы вычислили параметр size . Затем мы создали экземпляр списка пустых ведер и вставили элементы на основе их значения и размера каждого ведра.

После вставки мы вызываем insertion_sort() на каждом из ведер:

def insertion_sort(bucket):
    for i in range (1, len (bucket)):
        var = bucket[i]
        j = i - 1
        while (j >= 0 and var < bucket[j]):
            bucket[j + 1] = bucket[j]
            j = j - 1
        bucket[j + 1] = var

И с этим на месте давайте заполним список и выполним сортировку по ведру:

def main():
    input_list = [1.20, 0.22, 0.43, 0.36,0.39,0.27]
    print('ORIGINAL LIST:')
    print(input_list)
    sorted_list = bucket_sort(input_list)
    print('SORTED LIST:')
    print(sorted_list)

Запуск этого кода вернет:

Original list: [1.2, 0.22, 0.43, 0.36, 0.39, 0.27]
Sorted list: [0.22, 0.27, 0.36, 0.39, 0.43, 1.2]

Сложность сортировки Ведра по Времени

Наихудшая сложность

Если коллекция, с которой мы работаем, имеет короткий диапазон (как в нашем примере) – обычно много элементов в одном ведре, где много ведер пусто.

Если все элементы попадают в одно и то же ведро, сложность зависит исключительно от алгоритма, который мы используем для сортировки содержимого самого ведра.

Поскольку мы используем сортировку вставки – ее наихудшая сложность сияет, когда список находится в обратном порядке. Таким образом, наихудшая сложность для сортировки ведра также равна O(n 2 ) .

Сложность в лучшем Случае

В лучшем случае все элементы уже будут отсортированы. Кроме того, элементы распределены равномерно. Это означает, что каждое ведро будет иметь одинаковое количество элементов.

Тем не менее, создание ведер займет O(n) , а сортировка вставки займет O(k) , что даст нам O(n+k) сложность.

Средняя сложность случая

Средний случай встречается в подавляющем большинстве реальных коллекций. Когда коллекция, которую мы хотим отсортировать, является случайной . В этом случае сортировка ведра занимает O(n) до конца, что делает ее очень эффективной .

Вывод

Подводя итог, мы начали с того, что познакомились с тем, что такое сортировка по ведрам, и продолжили обсуждение того, что нам нужно знать, прежде чем мы перейдем к ее реализации в Python. После внедрения мы провели быстрый анализ сложности.