【数据结构与算法】最小堆 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;
	}
}



你可能感兴趣的:(数据结构与算法)