你不会实现堆IN二叉树,因为堆是A二叉树。堆维护以下 order 属性 - 给定节点 V,其父节点大于或等于 V。堆也是完整的binary tree。我在 uni 上过 ADS 课程,所以稍后我将在答案中为您提供我在 Java 中的堆实现。仅列出您获得的主要方法复杂性:
- 大小() O(1)
- isEmpty() O(1)
- insert() O(logn)
- removeMin() O(logn)
- min() O(1)
这是我的Heap.java 文件:
public class Heap<E extends Comparable<E>> {
private Object S[];
private int last;
private int capacity;
public Heap() {
S = new Object[11];
last = 0;
capacity = 7;
}
public Heap(int cap) {
S = new Object[cap + 1];
last = 0;
capacity = cap;
}
public int size() {
return last;
}
//
// returns the number of elements in the heap
//
public boolean isEmpty() {
return size() == 0;
}
//
// is the heap empty?
//
public E min() throws HeapException {
if (isEmpty())
throw new HeapException("The heap is empty.");
else
return (E) S[1];
}
//
// returns element with smallest key, without removal
//
private int compare(Object x, Object y) {
return ((E) x).compareTo((E) y);
}
public void insert(E e) throws HeapException {
if (size() == capacity)
throw new HeapException("Heap overflow.");
else{
last++;
S[last] = e;
upHeapBubble();
}
}
// inserts e into the heap
// throws exception if heap overflow
//
public E removeMin() throws HeapException {
if (isEmpty())
throw new HeapException("Heap is empty.");
else {
E min = min();
S[1] = S[last];
last--;
downHeapBubble();
return min;
}
}
//
// removes and returns smallest element of the heap
// throws exception is heap is empty
//
/**
* downHeapBubble() method is used after the removeMin() method to reorder the elements
* in order to preserve the Heap properties
*/
private void downHeapBubble(){
int index = 1;
while (true){
int child = index*2;
if (child > size())
break;
if (child + 1 <= size()){
//if there are two children -> take the smalles or
//if they are equal take the left one
child = findMin(child, child + 1);
}
if (compare(S[index],S[child]) <= 0 )
break;
swap(index,child);
index = child;
}
}
/**
* upHeapBubble() method is used after the insert(E e) method to reorder the elements
* in order to preserve the Heap properties
*/
private void upHeapBubble(){
int index = size();
while (index > 1){
int parent = index / 2;
if (compare(S[index], S[parent]) >= 0)
//break if the parent is greater or equal to the current element
break;
swap(index,parent);
index = parent;
}
}
/**
* Swaps two integers i and j
* @param i
* @param j
*/
private void swap(int i, int j) {
Object temp = S[i];
S[i] = S[j];
S[j] = temp;
}
/**
* the method is used in the downHeapBubble() method
* @param leftChild
* @param rightChild
* @return min of left and right child, if they are equal return the left
*/
private int findMin(int leftChild, int rightChild) {
if (compare(S[leftChild], S[rightChild]) <= 0)
return leftChild;
else
return rightChild;
}
public String toString() {
String s = "[";
for (int i = 1; i <= size(); i++) {
s += S[i];
if (i != last)
s += ",";
}
return s + "]";
}
//
// outputs the entries in S in the order S[1] to S[last]
// in same style as used in ArrayQueue
//
}
HeapException.java:
public class HeapException extends RuntimeException {
public HeapException(){};
public HeapException(String msg){super(msg);}
}
为您提供 O(logn) 性能的有趣部分是 downHeapBubble() 和 upHeapBubble() 方法。我很快就会对它们进行很好的解释。
upHeapBubble() 在向堆中插入新节点时使用。因此,当您插入时,您插入到最后一个位置,然后您需要像这样调用upHeapBubble():
last++;
S[last] = e;
upHeapBubble();
然后将最后一个元素与它的父元素进行比较,如果父元素更大 - 交换:这是最大 logn 次,其中 n 是节点数。所以这里是登录性能。
对于删除部分 - 您只能删除 min - 最高节点。所以当你删除它时——你必须将它与最后一个节点交换——但是你必须维护堆属性并且你必须做一个downHeapBubble()。如果节点大于它的子节点,则与最小的节点交换,依此类推,直到您没有任何子节点或您没有更小的子节点。这可以在最大登录时间完成,因此这里是登录性能。您可以通过查看二叉树图片here
来解释为什么此操作可以完成最大登录次数