Как написать метод sortRemove для MaxHeapPriorityQueue в Java? - PullRequest
1 голос
/ 14 мая 2019

Я работаю над вспомогательным методом private E sortRemove () для моего статического метода HeapSort.Позвольте мне отметить, что эта куча является MaxHeapPriorityQueue, у которого все элементы имеют дочерний элемент, значение которого меньше родительского.

Я пытаюсь

  • Повторно вызывать метод удаления до тех пор, пока куча не станет пустой.
  • Но сделать так, чтобы при удалении элемента он перемещалсядо конца массива вместо полного выселения из массива.
  • Когда вы закончите, вуаля!Массив отсортирован.

Я пытаюсь выяснить, как этот алгоритм вписывается в мой код.

Поэтому у меня есть:

public class MaxHeapPriorityQueue<E extends Comparable<E>>
{
private E[] elementData;
private int size;

@SuppressWarnings("unchecked")
public MaxHeapPriorityQueue()
{
    elementData = (E[]) new Comparable[10];
    size = 0;
}
public static void heapSort(Comparable[] a, int size)
{
    MaxHeapPriorityQueue mhpq = new MaxHeapPriorityQueue();
    mhpq.elementData = a;
    mhpq.size = size;

    for (int i = (size/2)-1; i >= 0; i--)
    {
        mhpq.bubbleDown(i);
    }
    for(int i = size-1; i >= 0; i--)
    {
        a[i] = mhpq.sortRemove();
    }
}
private E sortRemove()
{
    for (int i = (size-1)/2; i >= 0; i--)  //down to 0
    {
        bubbleDown(i);
    }
    while(size > 0)
    {
        swap(elementData, size, 0); // puts the largest item at the end of the heap
        size = size - 1;          // decrease remaining count
        bubbleDown(0);    // adjust the heap
    }
    return sortRemove();
}
}

Я знаю, что это не обязательно правильный алгоритм, но, насколько я понимаю, я хочу получить первое значение, которое является наибольшим,последний элемент в списке, таким образом, он сортируется.Метод HeapSort также не обязательно точен, поэтому у меня есть другой вопрос, касающийся этого ( Как создать метод HeapSort для массива в Java? ), в этом я хочу в первую очередь сосредоточиться наметод sortRemove.

Ответы [ 2 ]

2 голосов
/ 14 мая 2019

Сортировка кучи на месте состоит из двух этапов:

  1. Создание кучи из произвольного массива.
  2. Изменение порядка результирующего массива так, чтобы он сортировался.

Вы можете сделать первый шаг за время O (n), используя алгоритм makeHeap.Я показываю основную идею ниже.Предположим, что массив a имеет длину n.

for i = (n-1)/2 downto 0
    bubbleDown(i);

Обратите внимание, что вы начинаете с середины и возвращаетесь к началу массива.Позвольте мне привести пример того, как это работает.Скажем, вам дан массив [1,5,3,4,6,7,2].Представленный в виде двоичной кучи, он становится:

        1
    5       3
 4    6   7   2

(n-1)/2 равен 3, поэтому мы начнем со значения 4 в куче.Это не может двигаться, поэтому мы переходим к значению 3.Мы строим максимальную кучу, поэтому мы проверяем двух дочерних элементов, чтобы узнать, больше ли один из них. Если это так, мы поменяемся местами с самым большим из двух дочерних элементов.Это дает:

        1
    5       7
 4    6   3   2

Переходя назад к значению 5, мы видим, что 6 больше, и поэтому мы меняем эти два элемента:

        1
    6       7
 4    5   3   2

И, наконец,корневой элемент.7 больше, чем дети, поэтому мы поменяемся местами:

        7
    6       1
 4    5   3   2

И, поскольку мы еще не достигли уровня листьев, мы снова проверяем и меняем местами 1 с 3:

        7
    6       3
 4    5   1   2

И там у вас есть допустимая максимальная куча.Этот алгоритм всегда работает.

Обратите внимание, что ваша идея начать с корня и работать вниз не всегда приведет к правильной куче.Возьмите начальную позицию, которую я дал ранее:

        1
    5       3
 4    6   7   2

Если я начну с вершины и поднимусь вниз, то мы поменяемся местами 1 и 5, а затем поменяем 5 и 6,давая:

        6
    5       3
 4    1   7   2

Мы смотрим на 5, и это не должно быть пузырьком вниз.Затем мы смотрим на 3 и меняем местами 7, в результате чего:

        6
    5       7
 4    1   3   2

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

Итак, makeHeap для построения кучи.

Шаг 2: сортировка.

Сортировка массивакак только вы создали кучу, это довольно легко.Базовый алгоритм:

while n > 0
    swap(a[0], a[n-1]) // puts the largest item at the end of the heap
    n = n - 1          // decrease remaining count
    bubbleDown(0)      // adjust the heap

Это всего лишь небольшое изменение стандартной функции removeLargest из любой реализации max heap.Вместо того, чтобы удалять и возвращать корневой элемент, вы заменяете его последним элементом в куче.

Давайте посмотрим, как это работает.Учитывая начальную кучу:

        7
    6       3
 4    5   1   2

Поменяйте местами 7 на 2, уменьшите счет и уменьшите число:

        6
    5       3
 4    2   1   7

Поменяйте местами 6 на 1, уменьшите счет и уменьшите число:

        5
    4       3
 1    2   6   7

Поменяйте местами 5 с 2, уменьшите счет и уменьшите число:

        4
    2       3
 1    5   6   7

Поменяйте местами 4 с 1, уменьшите счет и уменьшите число:

        3
    2       1
 4    5   6   7

... И я на этом остановлюсь, потому что я думаю, что вы поняли идею.

Это действительно так просто.Если у вас есть реализация max heap с методами insert и removeLargest и стандартными вспомогательными методами siftUp и bubbleDown (или как вы их называете), то добавление метода сортировки - это вопрос создания этих двух маленькихфункции, которые вызывают вспомогательные методы.

Рекомендуется heapSort метод:

public static void heapSort(Comparable[] a, int size)
{
  MaxHeapPriorityQueue elementData = new MaxHeapPriorityQueue();
  // PriorityQueue<Comparable> pq = new PriorityQueue();

  for (int i = (size-1)/2; i >= 0; i--)  //down to 0
  {
    bubbleDown(i);
  }
  while(size > 0)
  {
    swap(elementData, size, 0); // puts the largest item at the end of the heap
    size = size - 1;          // decrease remaining count
    bubbleDown(0);    // adjust the heap
  }
  // The array is sorted.
}
0 голосов
/ 16 мая 2019

Вот что я придумала

Мы сохраняем это исходное значение где-то для его сохранения.

Затем изменяем индекс первого значения на последний и уменьшаем размер.

Затем мы всплываем только с индексом 0.

Затем мы возвращаем значение.

private E sortRemove()
{
    E value = elementData[0];
    elementData[0] = elementData[size-1];
    size--;
    bubbleDown(0);
    return value;
}
...