写在之前
1.自定义实现采用数组作为内部数据结构
2.内部数组通过resize方法进行扩容,每次只是简单的扩展为原来的2倍
3.集中实现方式的主要区别在于siftDown方法
4.以下给出关键代码,更多详细信息请看附件源码
?
实现方式一(递归实现)
关键代码:
class="java" name="code"> @Override protected void siftDown(int index) { int len = totalCount - 1; while(left(index) <= len) { int left = left(index); int right = right(index); if(left > len) { break; } int currentMin = left; if(right <= len && arr[currentMin] > arr[right]) { currentMin = right; } if(arr[currentMin] >= arr[index]) { break; } swap(arr, currentMin, index); index = currentMin; } }
?
实现方式二(循环实现)
关键代码:
@Override protected void siftDown(int index) { int len = totalCount - 1; while(left(index) <= len) { int left = left(index); int right = right(index); if(left > len) { break; } int currentMin = left; if(right <= len && arr[currentMin] > arr[right]) { currentMin = right; } if(arr[currentMin] >= arr[index]) { break; } swap(arr, currentMin, index); index = currentMin; } }
?
实现方式三(直接构建堆)
关键代码:
@Override protected void siftDown(int index) { int len = totalCount - 1; while(left(index) <= len) { int left = left(index); int right = right(index); if(left > len) { break; } int currentMin = left; if(right <= len && arr[currentMin] > arr[right]) { currentMin = right; } if(arr[currentMin] < arr[index]) { swap(arr, currentMin, index); } //进入下一个非叶子节点 index++; } }
?
实现方式四(JDK中的实现)
1.siftUp方法:
protected void siftUp(int k, int x) { while (k > 0) { int parent = parent(k); int e = arr[parent]; if (x >= e) break; arr[k] = e; k = parent; } arr[k] = x; }
?2.siftDown方法:
/** * 指定index位置的值为x,并为x在堆中找到合适位置 * @param index * @param x */ private void siftDown(int index, int x) { int half = totalCount >>> 1; while (index < half) { int currentMin = left(index); int right = right(index); if (right < totalCount && arr[currentMin] > arr[right]) currentMin = right; if (x <= arr[currentMin]) break; //将index位置设置为最小节点值 arr[index] = arr[currentMin]; //迭代 index = currentMin; } //将最终值放入合适位置 arr[index] = x; }
?
其他的一下关键方法
1.siftUp方法:
@Override protected void siftUp(int index) { int parent = parent(index); while(index > 0 && arr[index] < arr[parent]) { swap(arr, index, parent); index = parent; parent = parent(index); } }
?2.add方法:
@Override public boolean add(int ele) { if(totalCount == arr.length) { //扩容 grow(); } int i = totalCount; arr[i] = ele; if(totalCount == 1) { return true; } //调整元素位置确保为小根堆 siftUp(i); totalCount++; return true; }
?3.poll方法:
@Override public int poll() { int result = arr[0]; arr[0] = arr[--totalCount]; siftDown(0); return result; }
?5.remove方法:
@Override public int remove(int ele) { //内部数据为空 if(totalCount < 1) { return -1; } //计算元素位置 int index = indexOf(ele); if(index < 0) { return -1; } return removeAt(index); }
?6.removeAt方法:
@Override protected int removeAt(int idx) { if(idx < 0 || idx >= totalCount) { return -1; } int result = arr[idx]; //将删除元素与最后一个元素交换位置 if(idx != totalCount -1) { arr[idx] = arr[totalCount - 1]; } //位置交换之后队列长度减一 totalCount--; //如果队列长度大于1,而且删除的元素位置不在队尾则重新调整堆 if(totalCount > 1 && idx != totalCount) { siftDown(idx); } return result; }
?
?
?