数据结构之堆

/**
 * 数据结构学习之队列之最大优先级队列接口
 * @author Sking
 */
package 堆;

public interface MaxPriorityQueue {
	/**
	 * 判断最大优先级队列是否为空
	 * @return 最大优先级队列为空则返回true,否则false
	 */
	public boolean isEmpty();

	/**
	 * 返回最大优先级队列的元素个数
	 * @return 最大优先级队列的元素个数
	 */
	public int size();

	/**
	 * 返回最大优先级队列的“最大”元素
	 * @return 最大优先级队列的“最大”元素,如果队列为空则返回null
	 */
	public Comparable<?> getMax();

	/**
	 * 插入指定元素到最大优先级队列
	 * @param theObject 待插入元素
	 */
	public void put(Comparable<?> theObject);

	/**
	 * 移除最大优先级队列的“最大”元素,并返回
	 * @return 最大优先级队列的“最大”元素,队列为空则返回null
	 */
	public Comparable<?> removeMax();
}


 

/**
 * 数据结构学习之队列之最大优先级队列
 * 使用数组形式的堆结构实现最大优先队列
 * @author Sking*
 */
package 堆;

import java.lang.reflect.Array;

public class MaxHeap{
	@SuppressWarnings("rawtypes")
	Comparable[] heap;// 堆数组,索引位置0不使用
	int size;// 元素个数

	/**
	 * 指定堆数组初始容量的构造方法
	 * 
	 * @param initialCapacity
	 *            堆数组的初始容量
	 */
	public MaxHeap(int initialCapacity) {
		if (initialCapacity < 1)
			throw new IllegalArgumentException("initialCapacity must be >= 1");
		heap = new Comparable[initialCapacity + 1];
		size = 0;
	}

	/**
	 * 无参构造函数,默认堆数组的初始容量为10
	 */
	public MaxHeap() {
		this(10);
	}

	/**
	 * 判断堆数组是否为空
	 */
	public boolean isEmpty() {
		return size == 0;
	}

	/**
	 * 获取堆数组中的元素个数
	 */
	public int size() {
		return size;
	}

	/**
	 * 获取堆数组中的首元素(“最大元素')
	 */
	@SuppressWarnings({ "rawtypes" })
	public Comparable getMax() {
		return (size == 0) ? null : heap[1];
	}

	/**
	 * 插入元素导最大堆中,重新调整使数组仍保持“堆特性”
	 * 
	 * 实现方法:将插入元素放在数组尾部,递归比较当前元素与
	 * 父亲节点元素 不满足堆特性的条件,则递归向上往“根"的方
	 * 向冒泡(比较移动),直到新元素的父节点元素大于”它“
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void put(Comparable theElement) {
		if (size == heap.length - 1) {// 堆数组已满,分配新空间
			/*
			 * heap.getClass().getComponentType()
			 * 获取数组元素类型对应的Class对象
			 * Array.newInstance(Class<?>,int)
			 * 指定元素类型和数组长度创建新的数组实例
			 */
			Comparable[] newArray = (Comparable[]) Array.newInstance(heap
					.getClass().getComponentType(), 2 * heap.length);
			// 复制堆元素到新数组中
			System.arraycopy(heap, 0, newArray, 0, heap.length);
			heap = newArray;
		}
		int currentNode = ++size;// 新元素插入索引
		// 新元素沿着到根的路径向上冒泡(比较交换),直到新元素的父结点元素“大于”它
		while (currentNode != 1
				&& heap[currentNode / 2].compareTo(theElement) < 0) {
			// 父节点元素下移
			heap[currentNode] = heap[currentNode / 2];
			currentNode /= 2;
		}
		heap[currentNode] = theElement;
	}

	/**
	 * 从最大堆中移除堆数组的首元素(”最大元素“)
	 * 
	 * 实现方法:先用堆数组的最后一个元素填补根节点,然后从根
	 * 位置开始 沿着不满足堆特性的路径递归进行调整,找到最后
	 * 一个元素的适合位置,使其成为最大堆。每次迭代均会涉及到
	 * 一棵子树(包含三个元素),找出 该子树中的最大元素作为当
	 * 前子树的根节点。如果最大元素就是数组末尾元素 则递归停止,
	 * 否则交换元素位置,并递归调整。
	 * 
	 * 注意点:最大元素一开始就被保存,用于最后的返回值。所以调
	 * 整操作可以安全使用 首元素。并且调整以后数组末尾位置将空出。
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public Comparable removeMax() {
		if (size == 0)// 堆数组为空
			return null;
		Comparable maxElement = heap[1];// ”最大"元素
		Comparable lastElement = heap[size--];//堆数组的最后一个元素
		int currentNode = 1, child = 2;//当前子树的根节点索引和左孩子索引
		while (child <= size) {
			// 每次迭代筛选出子树的最大元素作为该子树的根节点,交换元素位置
			if (child < size && heap[child].compareTo(heap[child + 1]) < 0)
				child++;
			if (lastElement.compareTo(heap[child]) >= 0)
				break;// 已满足最大堆特性
			heap[currentNode] = heap[child];
			currentNode = child;
			child *= 2;
		}// currentNode指示当前被考察的子树根节点位置
		heap[currentNode] = lastElement;
		return maxElement;
	}

	/**
	 * 将输入数组(长度为n)初始化为最大堆
	 * 实现方法:从有孩子节点的元素开始(索引为n/2),如果以该位置为根的子树
	 * 满足最大堆特性,则无需调整,否则通过交换位置进行调整。依次调整i,i-1,i-2..
	 * 位置为根的子树,直到数组的首元素为止。
	 * @param theHeap 输入的数组,可能不满足堆特性
	 * @param theSize 输入数组元素个数
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void initialize(Comparable[] theHeap, int theSize) {
		heap = theHeap;
		size = theSize;
		for (int root = size / 2; root >= 1; root--) {
			Comparable rootElement = heap[root];
			int child = 2 * root;
			while (child <= size) {
				if (child < size && heap[child].compareTo(heap[child + 1]) < 0)
					child++;
				if (rootElement.compareTo(heap[child]) >= 0)
					break;
				heap[child / 2] = heap[child];
				child *= 2;
			}
			heap[child / 2] = rootElement;
		}
	}

	/**
	 * 指定格式打印堆数组[元素1,元素2,元素3...]
	 */
	public String toString() {
		StringBuffer s = new StringBuffer();
		s.append("The " + size + " elements are [");
		if (size > 0) {
			s.append(heap[1]);
			for (int i = 2; i <= size; i++)
				s.append(", " + heap[i]);
		}
		s.append("]");
		return new String(s);
	}

}


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值