Алгоритм сортировки кучей (с Code in Python и C++)

⚡ Умное резюме

Алгоритм сортировки кучей сортирует массив, создавая бинарную кучу и многократно извлекая её содержимое.tracпомещая его корневое значение в отсортированную секцию. Этот ресурс объясняет алгоритм heapify, максимальную и минимальную кучи, псевдокод и полный код. Python и C++ Реализации с анализом временной сложности.

  • ???? Основная идея: Сортировка кучей строит полную бинарную кучу, а затем многократно...tracЭто корень, который формирует отсортированный порядок.
  • 🔺 Heapify: Операция heapify восстанавливает свойство кучи путем обмена.ping родитель со своим более крупным ребенком.
  • 🇧🇷 Массивное хранилище: Куча хранится в массиве, где узел с индексом i имеет дочерние узлы с индексами 2i+1 и 2i+2.
  • 🇧🇷 Сложность: Сортировка кучей работает за время O(n log n) во всех случаях и использует дополнительное пространство O(1).
  • 💻 Code При условии: Работы Python и C++ Программы демонстрируют операции кучирования, построения кучи и полной сортировки.

Что такое алгоритм пирамидальной сортировки?

Сортировка кучей — один из популярных и быстрых алгоритмов сортировки. Он основан на структуре данных полного бинарного дерева. Для максимальной кучи мы будем искать максимальный элемент и помещать его на вершину. Мы поместим его на родительский узел бинарного дерева.

Допустим, дан массив, данные = [10,5, 7, 9, 4, 11, 45, 17, 60].

В массиве, если i-й (i=0,1,2,3…) индекс является родительским узлом, то (2i+1) и (2i+2) будут левым и правым дочерними узлами. Создание полного двоичного дерева с помощью этого массива будет выглядеть так:

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

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

Применение пирамидальной сортировки

Вот некоторые примеры использования алгоритма сортировки кучи:

  • Для построения «приоритетных очередей» требуется пирамидальная сортировка. Потому что пирамидальная сортировка сохраняет сортировку элемента после каждой вставки.
  • Структура данных кучи эффективна при поиске kth наибольший элемент в заданном массиве.
  • Ядро Linux использует сортировку кучи по умолчанию. алгоритм сортировки так как имеет пространственную сложность O(1).

Создайте пирамидальную сортировку с примером

Здесь мы построим максимальную кучу из следующего полного двоичного дерева.

Создайте пирамидальную сортировку с примером

Листовыми узлами являются 17, 60, 4, 11 и 45. У них нет дочерних узлов. Вот почему они являются листовыми узлами. Итак, мы запустим метод heapify из родительского узла. Вот шаги:

Шаг 1) Выберите самое левое поддерево. Если дочерние узлы больше, поменяйте местами родительский узел с дочерним узлом.

Здесь родительским узлом является 9. А дочерними узлами являются 17 и 60. Поскольку 60 является самым большим, 60 и 9 будут заменены местами для сохранения максимальная куча.

Создайте пирамидальную сортировку с примером

Шаг 2) Теперь самое левое поддерево разбито на кучу. Следующий родительский узел — 7. У этого родителя есть два дочерних узла, самый большой — 45. Таким образом, 45 и 7 будут заменены местами.

Создайте пирамидальную сортировку с примером

Создайте пирамидальную сортировку с примером

Шаг 3) Узлы 60 и 4 имеют родительский узел 5. Поскольку «5» меньше дочернего узла 60, он будет заменен.

Создайте пирамидальную сортировку с примером

Создайте пирамидальную сортировку с примером

Шаг 4) Теперь у узла 5 есть дочерний узел 17,9. Это не поддерживает свойство максимальной кучи. Итак, 5 будет заменено на 17.

Создайте пирамидальную сортировку с примером

Шаг 5) Узел 10 будет заменен на 60, затем заменен на 17. Процесс будет выглядеть следующим образом.

Создайте пирамидальную сортировку с примером

Создайте пирамидальную сортировку с примером

Шаг 6) До шага 5 мы создали максимальную кучу. Каждый родительский узел больше своих дочерних узлов. Корневой узел имеет максимальное значение (60).

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

Этот процесс называется «extracт макс». Поскольку 60 — это максимальный узел, мы зафиксируем его позицию на нулевом индексе и создадим кучу без узла 0.

Создайте пирамидальную сортировку с примером

Создайте пирамидальную сортировку с примером

Шаг 7) Поскольку 60 удаляется, следующее максимальное значение равно 45. Мы выполним процесс «Ex».trac"t Max" снова с узла 45.

На этот раз мы получим 45 и заменим корневой узел его преемником 17.

Нам нужно выступить»Extracт Макс.», пока все элементы не будут отсортированы.

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

Создайте пирамидальную сортировку с примером

Что такое двоичная куча?

Двоичная куча — это своего рода полная бинарное дерево структура данных. В такой древовидной структуре родительский узел либо больше, либо меньше дочерних узлов. Если родительский узел меньше, то куча называется «Минимальной кучей», а если родительский узел больше, куча называется «Максимальной кучей».

Вот примеры минимальной кучи и максимальной кучи.

Минимальная куча и максимальная куча
Минимальная куча и максимальная куча

Если на приведенном выше рисунке вы заметили «Минимальную кучу», родительский узел всегда меньше своих дочерних узлов. В голове дерева мы можем найти наименьшее значение 10.

Аналогично, для «Максимальной кучи» родительский узел всегда больше дочерних узлов. Максимальный элемент присутствует в головном узле для «Максимальной кучи».

Что такое «Heapify»?

«Heapify» — это принцип кучи, который обеспечивает положение узла. В Heapify максимальная куча всегда поддерживает связь с родительским и дочерним узлами, и родительский узел будет больше, чем дочерние узлы.

Например, если добавляется новый узел, нам нужно изменить форму кучи. Однако нам также может потребоваться изменить или поменять местами узлы или перестроить массив. Этот процесс изменения формы кучиping Куча называется "кучеобразующей".

Вот пример того, как работает heapify:

Добавление нового узла и Heapify
Добавление нового узла и heapify

Вот шаги для heapify:

Шаг 1) Добавлен узел 65 как правый дочерний элемент узла 60.

Шаг 2) Проверьте, больше ли вновь добавленный узел родительского.

Шаг 3) Поскольку он больше родительского узла, мы поменяли местами правый дочерний узел с его родителем.

Как построить кучу

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

Допустим, массив содержит всего n элементов. Если «i»-й индекс является родительским узлом, то левый узел будет находиться по индексу (2и+1), и правый узел будет по индексу (2и+2). Мы предполагаем, что индекс массива начинается с 0.

Используя это, давайте сохраним максимальную кучу в виде массива:

Представление максимальной кучи на основе массива
Представление максимальной кучи на основе массива

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

Вот шаги для создания максимальной кучи:

Шаг 1) Начните с листового узла.

Шаг 2) Найдите максимум между родителем и детьми.

Шаг 3) Поменяйте местами узлы, если дочерний узел имеет большее значение, чем родительский.

Шаг 4) Поднимитесь на один уровень выше.

Шаг 5) Выполните шаги 2,3,4, пока не достигнем индекса 0 или не отсортируем все дерево.

Вот псевдокод для рекурсивной кучи (максимальная куча):

def heapify():
  input→ array, size, i
  largest = i
  left = 2*i + 1
  right = 2*i + 2
if left<n and array[largest ] < array[left]:
  largest = left
if right<n and array[largest ] < array[right]:
  largest = right
If largest not equals i:
  swap(array[i],array[largest])
  heapify(array,n,largest)

Прозвище Code для сортировки кучей

Вот псевдокод алгоритма сортировки кучей:

Heapify(numbers as an array, n as integer, i as integer):
  largest = i
  left = 2i+1
  right= 2i+2
if(left<=n) and (numbers[i]<numbers[left])
  largest=left
if(right<=n) and (numbers[i]<numbers[right])
  largest=right
if(largest  != i)
  swap(numbers[i], numbers[largest])
  Heapify(numbers,n,largest)
HeapSort(numbers as an array):
  n= numbers.size()
for i in range n/2 to 1
  Heapify(numbers,n,i)
for i in range n to 2
  Swap numbers[i] with numbers[1]
  Heapify(numbers,i,0)

Пример сортировки кучей Code in C++

#include <iostream>
using namespace std;
void display(int arr[], int n)
{
    for (int i = 0; i < n; i++)
    {
        cout << arr[i] << "\t";
    }
    cout << endl;
}
void heapify(int numbers[], int n, int i)
{
    int largest = i;
    int left = 2 * i + 1;
    int right = 2 * i + 2;
    if (left < n && numbers[left] < numbers[largest])
    {
        largest = left;
    }
    if (right < n && numbers[right] < numbers[largest])
    {
        largest = right;
    }
    if (largest != i)
    {
	//uncomment the following line to see details in output
        //cout<<"Swapping "<< numbers[i]<< " and "<<numbers[largest]<<endl;
        swap(numbers[i], numbers[largest]);
        heapify(numbers, n, largest);
    }
}
void heapSort(int numbers[], int n)
{
    for (int i = n/2 - 1; i >= 0; i--)
    {
        heapify(numbers, n, i);
//uncomment the following line to see details in output
 //cout<<"Heapify:\t";
  //display(numbers,n);
    }
    for (int i = n - 1; i >= 0; i--)
    {
        swap(numbers[0], numbers[i]);
        heapify(numbers, i, 0);
    }
}
int main()
{
    int numbers[] = { 10,5, 7, 9, 4, 11, 45, 17, 60};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    cout<<"Initial Array:\t";
    display(numbers,size);
    heapSort(numbers, size);
    cout<<"Sorted Array (descending order):\t";
    display(numbers, size);
}

Выход:

Initial Array:  10      5       7       9       4       11      45      17      60
Sorted Array (descending order):  60      45      17      11      10      9       7       5       4

Пример сортировки кучей Code in Python

def display(arr):
    for i in range(len(arr)):
    print(arr[i], end = "\t")
print()
def heapify(numbers, n, i):
    largest = i
left = 2 * i + 1
right = 2 * i + 2
if left < n and numbers[left] < numbers[largest]:
    largest = left
if right < n and numbers[right] < numbers[largest]:
    largest = right
if largest != i:
    numbers[i], numbers[largest] = numbers[largest], numbers[i]
heapify(numbers, n, largest)
def heapSort(items, n):
    for i in range(n //2,-1,-1):
        heapify(items, n, i) for i in range(n - 1, -1, -1):
        items[0], items[i] = items[i], items[0] heapify(items, i, 0) numbers = [10, 5, 7, 9, 4, 11, 45, 17, 60] print("Initial List:\t", end = "") display(numbers) print("After HeapSort:\t", end = "") heapSort(numbers, len(numbers)) display(numbers)

Выход:

Initial List:   10      5       7       9       4       11      45      17      60
After HeapSort: 60      45      17      11      10      9       7       5       4

Анализ временной и пространственной сложности пирамидальной сортировки

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

  1. лучший случай
  2. Средний случай
  3. Худший случай

Куча реализована в виде полного двоичного дерева. Итак, на нижнем уровне бинарного дерева будет максимальное количество узлов. Если нижний уровень имеет n узлов, то верхний уровень будет иметь n/2 узлов.

Анализ временной и пространственной сложности

В этом примере уровень 3 содержит четыре элемента, уровень 2 — два элемента, а уровень 1 — один элемент. Если всего элементов n, высота или общий уровень будет равна Журнал2(П). Таким образом, вставка одного элемента может занять максимум итераций Log(n).

Когда мы хотим взять максимальное значение из кучи, мы просто берем корневой узел. Затем снова запустите heapify. Каждая куча занимает Журнал2(П) время. БывшийtracНахождение максимума занимает время O(1).

лучший Case Time Complexity для алгоритма Heap Sort

Когда все элементы массива уже отсортированы, для построения кучи потребуется время O(n). Потому что, если список отсортирован, вставка элемента займет постоянное время, равное O (1).

Таким образом, для создания максимальной или минимальной кучи в лучшем случае потребуется время O(n).

Средняя сложность случая для алгоритма пирамидальной сортировки

Вставка элемента или экспонатаtracДостижение максимального значения занимает время O(log(n)). Таким образом, средняя временная сложность алгоритма сортировки кучей составляет О(п лог(п)).

Наихудшая временная сложность алгоритма пирамидальной сортировки

Как и в среднем случае, в худшем случае мы можем выполнить heapify n раз. Каждая heapify будет стоить O(log(n)) времени. Таким образом, наихудшая временная сложность будет равна О(п лог(п)).

Пространственная сложность алгоритма пирамидальной сортировки

Сортировка кучей — это алгоритм, разработанный на месте. Это означает, что для выполнения задачи не требуется никакой дополнительной или временной памяти. Если мы увидим реализацию, то заметим, что мы использовали swap() для выполнения обмена узлами. Никакого другого списка или массива не требовалось. Итак, пространственная сложность равна O(1).

Часто задаваемые вопросы (FAQ)

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

Сортировка кучей гарантирует время O(n log n) во всех случаях и использует на O(1) больше пространства. Быстрая сортировка обычно быстрее на практике, но может ухудшиться до O(n²) при неудачных опорных элементах. Сортировка кучей жертвует некоторой скоростью ради надежности в худшем случае.

Как пирамидальная сортировка, так и сортировка слиянием работают за время O(n log n). Пирамидальная сортировка сортирует на месте, используя дополнительное пространство O(1), но является нестабильной. Сортировка слиянием стабильна, но требует дополнительного пространства O(n) для слияния.

Искусственный интеллект-тренеры могут анимировать процесс формирования кучи, показывать, как образуется максимальная куча, и tracкаждый эксtracШаг t-max. Эта визуальная интерактивная справка облегчает новичкам понимание того, как сортировка кучей упорядочивает массив.

Да. Искусственный интеллект, помогающий программировать, может переводить реализацию алгоритма сортировки кучей между такими языками, как... C++, Python и Java пока киping Логика остается неизменной. Вам все равно следует скомпилировать и протестировать преобразованный код, чтобы убедиться в правильности результата.

Подведем итог этой публикации следующим образом: