이진 트리
Java에는 다양한 유형의 데이터 구조가 있습니다. 힙은 이진 트리 라는 트리 구조를 기반으로 합니다 . 이진 트리는 노드로 구성되며 각 노드는 최대 2개의 자식 노드를 가질 수 있습니다.

최대 힙
최대 힙(또는 maxheap)은 완전한 이진 트리 입니다 . 중요한 점은 부모 노드가 왼쪽 및 오른쪽 자식 노드보다 크거나 같은 값을 가져야 한다는 것입니다. 이를 준수하지 않으면 최대 힙이 없습니다. 반면에 최소 힙은 루트가 가장 작은 값이고 연속 노드의 값이 증가하는 반대입니다. 각 자식 노드는 부모보다 크거나 같은 값을 가집니다. 또한 완전한 이진 트리입니다. 최대 힙의 예는 다음과 같습니다.
PriorityQueue 클래스
Java의 힙은 PriorityQueue 클래스를 사용하여 구현할 수 있습니다 . PriorityQueues는 컬렉션에서 가장 중요하거나 가장 중요하지 않은 항목을 찾는 데 사용됩니다. PriorityQueue 클래스는 java.util.package 에서 찾을 수 있습니다 . PriorityQueue는 대기열에서 특정 순서로 배치되도록 비교할 수 있는 개체로 구성되어야 합니다. PriorityQueue는 비교자를 가질 수 있으므로 개체 간의 비교가 이루어지고 이 비교에 따라 대기열이 형성됩니다. 예를 들면 다음과 같습니다.
import java.util.Comparator;
import java.util.PriorityQueue;
public class Main
{
public static void main(String[] args) {
// Create PriorityQueue with comparator for ascending order of array length
PriorityQueue intQueue = new PriorityQueue((a,b) -> a - b);
Integer [] array1 = {1, 2, 4, 6, 8, 9};
Integer [] array2 = {3, 6, 9};
Integer [] array3 = {2, 4, 8, 16, 32, 64, 128};
Integer [] array4 = {5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55};
Integer [] array5 = {4};
//Add the array lengths to intQueue
intQueue.add(array1.length);
intQueue.add(array2.length);
intQueue.add(array3.length);
intQueue.add(array4.length);
intQueue.add(array5.length);
//Write out contents of intQueue as stored
while (intQueue.size() != 0) {
System.out.println(intQueue.remove());
}
}
}
출력 제공:
1 3 6 7 11
이 예에서 intQueue 의 기본 크기 는 11이므로 명시되지 않았으며(일반적으로 비교기 앞의 첫 번째 인수) 비교기는 다음과 같이 지정되었습니다.
(a,b) -> a - b
이것은 intQueue 의 항목을 비교하고 오름차순 배열 길이로 정렬합니다.
최대 힙 생성을 위한 PriorityQueue 구현
PriorityQueue 클래스 는 기본적으로 비교기가 없는 최소 힙입니다. 최소 힙은 최대 힙의 반대이므로 루트는 가장 작은 값이고 연속적인 자식 노드는 루트 및 후속 부모 노드보다 크거나 같습니다. 이러한 이유로 max heap의 경우 비교기로 Java의 Collections 프레임워크에서 reverseOrder()를 사용해야 합니다 . 이렇게 하면 최소 힙이 아닌 최대 힙을 얻을 수 있습니다. 이 클래스에는 add() , contains() , remove() , poll() 및 peek() 와 같은 유용한 메서드가 있습니다 .방법 | 설명 | 시간 복잡도 |
---|---|---|
추가(J) | 트리 끝에 요소 J를 추가합니다. | O(LogN) |
제거(J) | 트리에서 값 J 제거 | 에) |
투표() | 트리의 최대 요소를 제거합니다. | O(LogN) |
몰래 엿보다() | 트리 맨 위에 있는 루트 요소를 반환합니다. | 오(1) |
포함(J) | J가 대기열에 있으면 true를 반환하고 그렇지 않으면 false를 반환합니다. | 에) |

mport java.util.Collections;
import java.util.PriorityQueue;
public class MaxHeap {
public static void writeQueue(PriorityQueue<Integer> priorityQueue)
{
// Write out elements in queue, priorityQueue, and remove them using poll()
while(priorityQueue.size() != 0)
{
System.out.println(priorityQueue.poll());
}
}
public static void writeMaxHeap(PriorityQueue<Integer> priorityQueue)
{
// Write out elements in queue as a max heap - root, left child, right child, etc
for (Integer element : priorityQueue) {
System.out.println(element);
}
}
public static void main(String args[])
{
// Array of numbers to create a max heap array from
int[] theArray = {5, 3, 13, 10, 99, 19, 6, 51, 9};
// theQueue is created
PriorityQueue<Integer> theQueue =
new PriorityQueue<Integer>(Collections.reverseOrder());
// Elements are added to theQueue
for (int i = 0 ; i <theArray.length; ++i)
{
theQueue.add(theArray[i]);
}
// The head or root element (priority element) is printed out
System.out.println("The root value is : " + theQueue.peek());
// Find size of theQueue. Use method size()
Integer s = theQueue.size();
System.out.println("Size of theQueue? " + s);
// All elements of theQueue are printed in terms of parent,
// left child, right child
System.out.println("theQueue written using for loop:");
writeMaxHeap(theQueue);
// Does theQueue contain 10? Use method contains()
boolean b = theQueue.contains(10);
System.out.println("Does theQueue contain 10? " + b);
// Erasing value 10 from array using remove()
theQueue.remove(10);
// All elements of theQueue are printed out and removed.
// Each one is the maximum value left in the queue.
// At the end theQueue will be empty
System.out.println("theQueue written out using poll():");
writeQueue(theQueue);
// Find size of theQueue. Use method size()
s = theQueue.size();
System.out.println("Size of theQueue? " + s);
}
}
산출:
99 대기열의 크기? 9 for 루프를 사용하여 작성된 theQueue 99 51 19 13 10 5 6 3 9 theQueue에 10이 포함되어 있습니까? poll() 99 51 19 13 9를 사용하여 작성된 theQueue 참 6 5 3 대기열 크기? 0
맥스 히피파이
Max Heapify 알고리즘은 이진 트리가 최대 힙인지 확인하는 데 사용됩니다. 우리가 노드 n에 있고 그 자식 노드, 왼쪽 및 오른쪽도 최대 힙 자체인 경우 최대 힙이 있습니다. 트리 전체에서 그렇지 않은 경우 최대 힙이 없습니다. Max Heapify 알고리즘은 maxheap 원칙을 준수하도록 트리를 정렬하는 데 사용됩니다. Max Heapify는 하나의 노드에서만 작동합니다. 요구 사항이 배열이 최대 힙 배열인 경우 모든 하위 트리는 한 번에 하나씩 루트 전에 maxheap으로 변환되어야 합니다. 알고리즘은 각 노드에서 사용해야 합니다. 이것은 N/2 노드에서 수행됩니다(잎은 최대 힙 요구 사항을 준수함). 힙의 시간 복잡도는 O(NlogN)이고 높이 X에 있는 한 노드의 시간 복잡도는 O(X)입니다. 다음 코드는 트리(배열)를 최대화하는 방법을 보여줍니다.
public class MaxHeapify
{
public static Integer[] maxHeapify(Integer[ ] array, Integer i)
{
// Create left-child and right-child for the node in question
Integer leftChild = 2 * i + 1;
Integer rightChild = 2 * i + 2;
// Assign maxVal to parent node, i
Integer maxVal = i;
// Set maxVal to greater of the two: node or left-child
if( leftChild < array.length && array[leftChild] > array[maxVal] )
maxVal = leftChild;
// Set maxVal to greater of the two: maxVal or right-child
if( rightChild < array.length && array[rightChild] > array[maxVal] )
maxVal = rightChild;
// Check if maxVal is not equal to parent node, then set parent node to
// maxVal, swap values and then do a maxheapify on maxVal
// which is now the previous parent node
if( maxVal != i )
{
Integer value = array[i];
array[i] = array[maxVal];
array[maxVal] = value;
array = maxHeapify(array, maxVal);
}
return array;
}
public static Integer[] maxHeapCreate(Integer array[])
{
// Call maxHeapify to arrange array in a max heap
Integer [] theNewArr = array;
for( Integer i = array.length/2; i >= 0; i-- )
theNewArr = maxHeapify(array, i);
return theNewArr;
}
public static void main(String[] args)
{
// Create array to be maxheapified, theArray,
// and array, newArray, to write results into, by calling maxheapCreate
// newArray will now be a maxheap
Integer[] theArray = {5, 3, 13, 10, 99, 19, 6, 51, 9};
Integer[ ] newArray = maxHeapCreate(theArray);
// Print out contents of newArray
System.out.println("newArray:");
for(int i = 0; i < newArray.length; ++i)
{
System.out.println(newArray[i]);
}
// Print out labelled contents of newArray
System.out.println(" root : " + newArray[0]);
for (int i = 0; i <= newArray.length/2 - 1; i++) {
System.out.print(" parent node : " + newArray[i] + " left child : " +
newArray[(2*i)+1] + " right child :" + newArray[(2*i)+2]);
System.out.println();
}
}
}
출력 제공:
newArray:99 51 19 10 3 13 65 9 루트 : 99 부모 노드 : 99 왼쪽 자식 : 51 오른쪽 자식 :19 부모 노드 : 51 왼쪽 자식 : 10 오른쪽 자식 :3 부모 노드 : 19 왼쪽 자식 : 13 오른쪽 자식 :6 부모 노드 : 10 왼쪽 자식 : 5 오른쪽 아이 :999999999 친노드: 99 좌자식: 51 우자식:19 친노드: 51 좌자식: 10 우자식:3 친노드: 19 좌자식: 13 우자식:6 친노드: 10 좌자식: 5 우자식:999 친노드: 99 좌자식: 51 우자식:19 친노드: 51 좌자식: 10 우자식:3 친노드: 19 좌자식: 13 우자식:6 친노드: 10 좌자식: 5 우자식:96 부모 노드: 10 왼쪽 자식: 5 오른쪽 자식:96 부모 노드: 10 왼쪽 자식: 5 오른쪽 자식:9
이 코드에서 theArray 가 생성되고 숫자로 채워집니다. 두 번째 배열 newArray 가 생성되고 이번에는 최대 힙 배열인 maxheapCreate 메서드의 결과가 포함됩니다. maxHeapCreate 메서드는 main 에서 호출되며 여기서 새 배열인 theNewArr 가 생성되고 maxHeapify 결과로 채워집니다. 이는 입력 배열 크기의 절반 이상을 반복하여 수행됩니다. 루프의 각 패스에 대해 maxHeapify 메서드 가 호출되어 배열 중간에 있는 요소에서 시작하여 첫 번째 요소로 끝납니다. maxHeapify 의 각 호출에 대해, 부모 노드 i의 왼쪽 자식과 오른쪽 자식을 찾고 세 개 중 가장 큰 것을 찾기 위해 검사를 수행하고 이를 maxVal 로 정의합니다 . maxVal이 부모 노드와 같지 않으면 교체가 수행되어 부모 노드와 maxVal 이 교체된 다음 이번에는 maxVal 에서 maxHeapify가 다시 호출되고 이전과 동일한 단계가 수행됩니다. 결국 최대 힙이 생성되고 더 이상 수행할 반복이 없습니다. 업데이트된 배열 array 는 이제 main에 newArray로 반환된 다음 각 연속 요소가 콘솔에 출력됩니다. newArray이제 최대 힙입니다. PriorityQueue를 사용하는 이전 예에서와 같이 숫자가 기록됩니다. 왼쪽 자식을 부모로, 첫 번째 왼쪽 자식의 오른쪽 자식을 부모로, 첫 번째 오른쪽 자식의 왼쪽 자식을 부모로 하는 등. 연속 요소 간에 비교가 이루어지기 때문에 PriorityQueue를 사용할 때와 순서가 약간 다릅니다. 반면 maxheapify 예에서는 노드가 배열의 다음 두 연속 요소와 비교되고 가장 큰 값으로 교환됩니다. 즉, 두 가지 다른 알고리즘이 사용됩니다. 둘 다 최대 힙을 생성합니다.
GO TO FULL VERSION