/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
******************************************************************************/
package com.badlogic.gdx.utils;
/** @author Nathan Sweet */
public class BinaryHeap<T extends BinaryHeap.Node> {
public int size = 0;
private Node[] nodes;
private final boolean isMaxHeap;
public BinaryHeap() {
this(16, false);
}
public BinaryHeap(int capacity, boolean isMaxHeap) {
this.isMaxHeap = isMaxHeap;
nodes = new Node[capacity];
}
public T add(T node) {
// Expand if necessary.
if (size == nodes.length) {
Node[] newNodes = new Node[size << 1];
System.arraycopy(nodes, 0, newNodes, 0, size);
nodes = newNodes;
}
// Insert at end and bubble up.
node.index = size;
nodes[size] = node;
up(size++);
return node;
}
public Node peek() {
if (size == 0)
throw new IllegalStateException("The heap is empty.");
return nodes[0];
}
public T pop() {
Node[] nodes = this.nodes;
Node popped = nodes[0];
nodes[0] = nodes[--size];
nodes[size] = null;
if (size > 0)
down(0);
return (T) popped;
}
public void setValue(T node, float value) {
float oldValue = node.value;
node.value = value;
if (value < oldValue ^ isMaxHeap)
up(node.index);
else
down(node.index);
}
private void up(int index) {
Node[] nodes = this.nodes;
Node node = nodes[index];
float value = node.value;
while (index > 0) {
int parentIndex = (index - 1) >> 1;
Node parent = nodes[parentIndex];
if (value < parent.value ^ isMaxHeap) {
nodes[index] = parent;
parent.index = index;
index = parentIndex;
} else
break;
}
nodes[index] = node;
node.index = index;
}
private void down(int index) {
Node[] nodes = this.nodes;
int size = this.size;
Node node = nodes[index];
float value = node.value;
while (true) {
int leftIndex = 1 + (index << 1);
if (leftIndex >= size)
break;
int rightIndex = leftIndex + 1;
// Always have a left child.
Node leftNode = nodes[leftIndex];
float leftValue = leftNode.value;
// May have a right child.
Node rightNode;
float rightValue;
if (rightIndex >= size) {
rightNode = null;
rightValue = isMaxHeap ? Float.MIN_VALUE : Float.MAX_VALUE;
} else {
rightNode = nodes[rightIndex];
rightValue = rightNode.value;
}
// The smallest of the three values is the parent.
if (leftValue < rightValue ^ isMaxHeap) {
if (leftValue == value || (leftValue > value ^ isMaxHeap))
break;
nodes[index] = leftNode;
leftNode.index = index;
index = leftIndex;
} else {
if (rightValue == value || (rightValue > value ^ isMaxHeap))
break;
nodes[index] = rightNode;
rightNode.index = index;
index = rightIndex;
}
}
nodes[index] = node;
node.index = index;
}
public String toString() {
if (size == 0)
return "[]";
Object[] nodes = this.nodes;
StringBuilder buffer = new StringBuilder(32);
buffer.append('[');
buffer.append(nodes[0]);
for (int i = 1; i < size; i++) {
buffer.append(", ");
buffer.append(nodes[i]);
}
buffer.append(']');
return buffer.toString();
}
/** @author Nathan Sweet */
static public class Node {
float value;
int index;
public Node(float value) {
this.value = value;
}
public float getValue() {
return value;
}
}
}