Куча является важной структурой в структуре данных. После понимания концепции и работы «куча» вы можете быстро освоить сортировку кучи.
Концепция кучи
Куча - это специальное полное двоичное дерево. Если значения всех узлов полностью двоичного дерева не меньше их детей, это называется большой корневой кучей (или большой верхней кучей); Если значения всех узлов не больше их детей, это называется небольшой корневой кучей (или маленькой верхней кучи).
В массиве (хранение корневого узла в номере подписка 0) легко получить следующее уравнение (эти два уравнения очень важны):
1. Узел с подписанием IS I, а координаты родительского узла-(I-1)/2;
2. Узел с подписанием IS I, координаты левого дочернего узла составляют 2*i+1, а правый дочерний узел составляет 2*i+2.
Установка и обслуживание кучи
Куча может поддерживать несколько операций, но теперь мы заботимся только о двух проблемах:
1. Учитывая неупорядоченный массив, как построить его как кучу?
2. После удаления верхнего элемента кучи, как отрегулировать композицию на новую кучу?
Давайте сначала посмотрим на второй вопрос. Предположим, у нас уже есть готовая большая корневая куча. Теперь мы удаляем корневой элемент, но мы не перемещаем другие элементы. Подумайте о том, что произошло: корневой элемент пуст, но другие элементы все еще сохраняют свойства кучи. Мы можем переместить последний элемент (кодовое имя а) в положение корневого элемента. Если это не особый случай, свойства кучи разрушаются. Но это просто потому, что А меньше, чем один из его детских элементов. Таким образом, мы можем переключить A и этот дочерний элемент на положение. Если A больше, чем все его дочерние элементы, куча регулируется; В противном случае повторите приведенный выше процесс, элемент А продолжает «тонуть» в структуре дерева, пока он не станет уместным, и массив восстанавливает свойства кучи. Приведенный выше процесс обычно называется «скрининг», и направление, очевидно, находится сверху вниз.
Это верно при удалении элемента, как и вставка нового элемента. Разница в том, что мы поместили новый элемент в конце, а затем сравниваем его с его родительским узлом, то есть фильтровать его снизу вверх.
Итак, как решить первую проблему?
Многие из книг о структурах данных, которые я прочитал, фильтрации от первого нелистного узла до фильтрации корневого элемента. Этот метод называется «метод фильтрации», который требует фильтрации петли N/2 элементов.
Но мы также можем учиться на идее «создавать что -то из ничего». Мы можем рассматривать первый элемент как кучу, а затем постоянно добавлять в него новые элементы. Этот метод называется «Метод вставки», который требует вставки цикла элементов (N-1).
Поскольку метод фильтрации и метод вставки различны, кучи, которые они создают, обычно различны для одних и тех же данных.
После грубого понимания кучи сортировка кучи - это естественная вещь.
Обзор алгоритма/идеи
Нам нужна восходящая последовательность, что мы должны делать? Мы можем создавать минимальную кучу, а затем каждый раз выводить корневой элемент. Тем не менее, этот метод требует дополнительного пространства (в противном случае он вызовет много движения элементов, и его сложность взлетает до O (n^2)). Что если нам нужна сортировка на месте (то есть, не допускается сложность пространства O (n) пространства)?
Есть способ. Мы можем построить максимальную кучу, а затем мы выводим максимальное значение в последней позиции, а второе максимальное значение в последней позиции ... поскольку максимальный выходной выход каждый раз освободит первое пространство, мы можем просто поместить такой элемент без необходимости дополнительного пространства. Очень красивая идея, верно?
открытый класс heapsort {public static void main (string [] args) {int [] arr = {50, 10, 90, 30, 70, 40, 80, 60, 20}; System.out.println («Перед сортировкой:»); for (int i = 0; i <arr.length; i ++) {System.out.print (arr [i]+""); } // куча сортировки (ARR); System.out.println (); System.out.println («После сортировки:»); for (int i = 0; i <arr.length; i ++) {System.out.print (arr [i]+""); }} / *** Сортировка кучи* / private static void heapsort (int [] arr) {// Создание последовательности, которая будет сортироваться в большую верхнюю кучу для (int i = arr.length / 2; i> = 0; i-) {heapadjust (arr, i, arr.length); } // Постепенно обмениваться корневым узлом каждого максимального значения с конечным элементом и отрегулируйте двоичное дерево, чтобы сделать его большой верхней кучей для (int i = arr.length-1; i> 0; i--) {swap (arr, 0, i); // Обмен верхней записью кучи с последней записью в настоящее время несортированной последующей Heapadjust (Arr, 0, I); // После обмена необходимо перепроверить, встречается ли куча большой верхней кучи. Если это не соответствует, это необходимо скорректировать}} / *** Процесс создания массива кучи* @param arr, который необходимо сортировать* @param i Количество корневого узла кучи, которое необходимо построить* @param n длины Array* / private void gupadjust (int arr, int i, int n) {int kild; int Отец; for (отец = arr [i]; LeatsChild (i) <n; i = child) {child = LeatsChild (i); // Если левый поддерек меньше правого поддерева, вам необходимо сравнить правую поддерею с родительским узлом, если (ребенок! = N - 1 && arr [ребенок] <arr [ребенок+1]) {child ++; // Увеличить серийный номер на 1, указывая на правое поддеревое} // Если родительский узел меньше, чем узел, вам нужно обмениваться, если (отец <arr [ребенок]) {arr [i] = arr [ребенок]; } else {break; // Большая верхняя конструкция кучи не разрушена, корректировка не требуется}} arr [i] = отец; } // Получите левый дочерний узел Private Static int Leatschild (int i) {return 2 * i + 1; } // Положение элемента подкачки arr [index1] = arr [index2]; arr [index2] = tmp; }}