手写Heap

public class MaxHeap<E extends Comparable<E>> {
	private List<E> data;//维护一个自定义数组
	public MaxHeap(int capacity) {
		data =new ArrayList<>(capacity);
	}
	public MaxHeap() {
		data=new ArrayList<>();
	}
	public int size() {
		return data.Size();
	}
	public boolean isEmpty() {
		return data.isEmpty();
	}
	//heapify操作:将数组转化为堆
	/**
	 * Heapify是指将数组转化为堆,这里先将数组直接看成是一个完全二叉树,
	 * 然后找到这棵二叉树的最后一个非叶子节点的节点,
	 * 也就是该树的最后一个节点的父节点。
	 * 然后从这个节点开始到根节点结束,执行sift down操作。
	 * 这样的时间复杂度为O(n)
	 */
	public MaxHeap(E[] arrs) {
	    data = new ArrayList<>(Arrays.asList(arrs));
	    for (int i = parent(size() - 1); i >= 0; i--) {
	        siftDown(i);
	    }
	}
	/**
	 * 返回完全二叉树的数组表示中,一个索引所表示的元素的父亲节点的索引
	 */
	private int parent(int index) {
		if(index==0) {
			throw new IllegalArgumentException("索引为0,没有父节点");
		}
		return (index-1)/2;
	}
	/**
	 * 返回完全二叉树的数组表示中,一个索引所表示的元素的左孩子节点的索引
	 */
	private int leftChild(int index) {
		return index*2+1;
	}
	/**
	 * 返回完全二叉树的数组表示中,一个索引所表示的元素的右孩子节点的索引
	 */
	private int rigthChild(int index) {
		return index*2+2;
	}
	/**
	 * 向堆中添加元素。
	 */
	public void add(E e) {
		data.addLast(e);
		siftUp(Size()-1);
	}
	private void siftUp(int index) {
		while(index>0 && data.get(parent(index)).compareTo(data.get(index))<0) {
			data.swap(index, parent(index));
			index=parent(index);
		}
	}
	/**
	 * 查看堆中的最大元素
	 */
	public E findMax() {
		if(data.getSize() == 0) {
            throw new IllegalArgumentException("堆为空");
		}
		return data.get(0);
	}
	/**
	 * 取出堆中最大元素
	 */
	public E extractMax() {
		E e=findMax();
		data.swap(0, size()-1);
		data.removeLast();
		siftDown(0);
		return e;
	}
	private void siftDown(int i) {
		while(leftChild(i)<size()) {
			int k=leftChild(i);
			if(k+1<size()&& data.get(k+1).compareTo(data.get(k))>0) {
				k++;
			}
			//此时,data[k]是leftChild和rightChild中最大值
			if(data.get(i).compareTo(data.get(k))>=0) {
				break;
			}
			data.swap(k, i);
			i=k;	
		}
	}
	public void swap(int i,int j) {
		E e=data[i];
		data[i]=data[j];
		data[j]=e;
	}
	/**
	 * 取出堆中最大的元素,并且替换成元素e
	 * Replace是指将堆中的最大元素取出,替换另一个进去。
	 * 因此可以直接将堆顶元素替换以后执行sift down操作,
	 * 这样时间复杂度就只有O(log n)。
	 */
	public E replace(E e) {
		E ret=findMax();
		data.set(0, e);
		siftDown(0);
		return ret;	
	}	
}

猜你喜欢

转载自blog.csdn.net/ThreeAspects/article/details/105722003
今日推荐