- 特点
- 堆是一棵完全二叉树,即除了最下边一层其余都是满的状态,最下边一层满足最后一个元素的左侧都是满状态。
- 堆有别于二叉树的一个特点就是其父节点是大于两个子节点的,两个子节点的左右分步没有硬性要求
- 堆通常以数组进行实现,常见的规律有 假设一个节点所在的索引为k,则其父节点所在的索引为k/2,两个子节点的索引分别为2k和2k+1
自己实现堆
public class Heap> { // 用来存储元素的数组 private T[] items; // 用来存储堆中元素的个数 private int size; public Heap(int capacity) { this.items = (T[]) new Comparable[capacity + 1]; this.size = 0; } private void exchange(int i, int j) { T temp = this.items[i]; this.items[i] = this.items[j]; this.items[j] = temp; } public T deleteMax() { // 交换最大的元素和最大索引处的值 T maxItem = items[1]; exchange(1, size); // 删除最大的元素,让完全二叉树中最右侧的元素变为临时的根节点 items[size] = null; this.size --; // 通过下沉算法调整堆,让根节点重新处于正确的位置,让堆重新有序 this.sink(1); return maxItem; } public void insert(T t) { items[++ size] = t; swim(size); } private void swim(int index) { while (index > 1) { // 与父节点进行比较 if (items[index].compareTo(items[index/2]) > 0) { exchange(index, index/2); } index = index / 2; } } private void sink(int index) { // 通过循环弊端的遍历当前索引的两个子节点 while (2*index <= size) { // 获取两个子节点中较大的那个 int maxChildIndex; if (2*index+1 <= size) { maxChildIndex = items[2*index].compareTo(items[2*index+1]) > 0 ? 2*index : 2*index+1; } else { maxChildIndex = 2*index; } // 比较当前索引处的值和两个子节点最大的值的关系 if (items[index].compareTo(items[maxChildIndex]) < 0) { // 当前索引比子节点的最大值小,就往两个子节点的最大者底下沉 exchange(index, maxChildIndex); index = maxChildIndex; } else { break; } } } public static void sort(Comparable[] source) { // 1. 构建堆 // 将source数组中的元素拷贝到堆数组中,形成一个无序待排序的堆 Comparable[] heap = new Comparable[source.length + 1]; System.arraycopy(source, 0, heap, 1, source.length); // 对堆中的元素做下沉调整(从堆长度的一般开始,往索引1处进行扫描) for (int i=(heap.length)/2; i>0; i--) { sinkSort(heap, i, source.length); } // 2. 堆排序 // 记录未排序的数组最大索引 int maxIndex = source.length; while (maxIndex != 1) { // 交换1索引处和未排序的最大索引处的值 Comparable temp = heap[1]; heap[1] = heap[maxIndex]; heap[maxIndex] = temp; maxIndex --; // 对交换之后的索引1处元素进行下沉调整,调整的区域为未排序区域 sinkSort(heap, 1, maxIndex); } // 3. 将排序好的数组转到原数组中 System.arraycopy(heap, 1, source, 0, source.length); } private static void sinkSort(Comparable[] heap, int targetIndex, int range) { while (2*targetIndex <= range) { int maxChildIndex; if (2*targetIndex+1 < range) { maxChildIndex = heap[2*targetIndex].compareTo(heap[2*targetIndex+1])>0 ? 2*targetIndex : 2*targetIndex+1; } else { maxChildIndex = 2*targetIndex; } if (heap[targetIndex].compareTo(heap[maxChildIndex]) >= 0) break; // 元素位置交换 Comparable temp = heap[targetIndex]; heap[targetIndex] = heap[maxChildIndex]; heap[maxChildIndex] = temp; targetIndex = maxChildIndex; } } }



