【数据结构与算法】最小堆 minheap
最小堆与最大堆实现思路一样,只不过顺序不同,这里只记录最小堆。
最小堆的定义是,一棵完全二叉树,每一个节点都大于等于其父节点。完全二叉树是叶子都在最后一层,且尽量靠左。
实现方面可以使用链表或者数组,这里使用数组。
如果使用数组,那么下标从0开始,父节点是i,则左子树是2*i+1,右子树是2*i+2。如果子节点是i,则父节点是(i-1)/2。
minheap的操作主要有两个,一个是add,思路是,新建一个节点在最后,然后不断地和父节点比较,如果小于父节点,就交换,直到大于等于或者root。
第二个操作是输出root,那么需要把最后一个节点移至root位置,然后重新梳理minheap,因为此时可能不再shiminheap了,梳理过程用函数minheapify实现。该函数的实现思路是传入一个i参数,表明以i为根的子树需要梳理,然后让i和比i小的子节点中的较小值交换,再递归地梳理被交换的节点。
下面是代码,这里没有考虑一些边界,比如数组的大小,或者输出空的heap的情况。
public class MinHeap { private int size = 0; private int[] heap = new int[100]; public void add(int data){ heap[size++] = data; int i = size - 1; while(i > 0 && heap[i] < heap[(i - 1) / 2]){ swap(i, (i - 1) / 2); i = (i - 1) / 2; } } public int top(){ size --; int r = heap[0]; swap(size, 0); minheapify(0); return r; } public void minheapify(int i){ int l = 2 * i + 1; int r = 2 * i + 2; int small = i; if(l < size && heap[i] > heap[l]){ small = l; } if(r < size && heap[r] < heap[small]){ small = r; } if(i != small){ swap(i, small); minheapify(small); } } private void swap(int i, int j){ int temp = heap[i]; heap[i] = heap[j]; heap[j]= temp; } public int size(){ return size; } }