前言
- 堆是一个完全二叉树,一层结点满了再把结点添加到下一层,每一层结点的添加顺序是从左到右。
- 父结点大于或者等于它的任意一个子结点
Heap实现
/**
* @version 1.0
* @anthor zsl on 2019/8/8
* @since jdk8
*/
public class Heap<E extends Comparable<E>> {
private ArrayList<E> list;
public Heap(){
list = new ArrayList<>();
}
public Heap(E[] objects){
list = new ArrayList<>();
for (E e:
objects) {
add(e);
}
}
/**
* @deprecated 向堆中添加一个元素
* @param e
*/
public void add(E e){
list.add(e);
int currentIndex = list.size()-1;
if(currentIndex == 0){
}
int parentIndex;
E parentObject,currentObject;
while (currentIndex != 0){
// 获取父元素
parentIndex = currentIndex/2;
parentObject = list.get(parentIndex);
// 获取子元素的值
currentObject = list.get(currentIndex);
if(parentObject.compareTo(currentObject) < 0){
list.set(parentIndex,currentObject);
list.set(currentIndex,parentObject);
currentIndex = parentIndex;
}else {
break;
}
}
}
/**
* @deprecated 删除堆顶
* @return E
*/
public E remove(){
if(list.size() == 0){
return null;
}
// 当前下标是数组做大下标
int currentIndex = list.size()-1;
/*记录根节点值并把最后一个节点覆盖到根节点,把当前结点重置成为根节点*/
E object = list.get(0);
list.set(0,list.get(currentIndex));
list.remove(currentIndex);
currentIndex = 0;
/*求出当前节点的左孩子与右孩子结点下标*/
int leftIndex = currentIndex*2+1;
int rightIndex = currentIndex*2 +2;
int limit = list.size()-1;
/*如果当前结点为叶子结点则退出循环*/
while (leftIndex < limit && rightIndex <= limit){
/*获取当前结点、左孩子结点、右孩子结点的值*/
E currentObject = list.get(currentIndex);
E leftObject = list.get(leftIndex);
E rightObject = list.get(rightIndex);
// 如果当前结点小于左孩子结点
if(currentObject.compareTo(leftObject) < 0){
list.set(currentIndex,leftObject);
list.set(leftIndex,currentObject);
currentIndex = leftIndex;
}else if(currentObject.compareTo(rightObject) < 0) {
// 如果当前结点小于右孩子结点的值
list.set(currentIndex,rightObject);
list.set(rightIndex,currentObject);
currentIndex = rightIndex;
}else {
// 如果当前结点既不小于左孩子结点又不小于右孩子结点的值
break;
}
//重置左孩子、右孩子的下标
leftIndex = currentIndex*2+1;
rightIndex = currentIndex*2 +2;
}
return object;
}
/**
* @deprecated 堆的大小
* @return int
*/
public int size(){
return list.size();
}
}
测试
public static void main(String[] args) {
Integer[] arr = {10,5,2,7,3,1,2};
System.out.println(Arrays.toString(execute(arr)));
}
public static Integer[] execute(Integer[] arr){
Heap<Integer> heap = new Heap<>(arr);
for(int i = arr.length-1; i >= 0; i--){
arr[i] = heap.remove();
}
return arr;
}
时间复杂度平均情况 | 时间复杂度最优情况 | 时间复杂度最差情况 | 空间复杂度 | 稳定性 |
---|
O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不稳定 |