堆排序

不登高山,不知天之高也;不临深溪,不知地之厚也。——《荀子》

 

/**
 * 
 * @author Jason Li 2014-5-28
 *  堆排序 堆数据结构可以看成一棵完全二叉树,分为最大堆和最小堆
 *  给定任一节点的下标i,则父节点下标i/2,左儿子2i,右儿子2i+1
 *  heapSize存储堆中的元素个数
 *  这里实现的是最大堆,即父节点的值 不小于子节点的值
 *  
 *  算法步骤:
 *  1. 对待排序数组建最大堆,则0位置存储了最大值
 *  2. 交换0位置元素与数组最后一个元素,heapSize减一
 *  3. 对0元素重新整理堆,使0位置仍然最大
 *  4. 重复2-3直到heapSize为1,完成排序
 * 
 */
public class HeapSort {
	public static void main(String[] args) {
		int[] dataArray = { 2, 6, 4, 9, 1, 7, 8, 3, 5 };
		HeapSort(dataArray);
		ArrayUtils.print(dataArray);
	}
	// 堆排序
	private static void HeapSort(int[] dataArray) {
		int heapSize = dataArray.length - 1;// 当前堆长度默认为数组长度
		BuildMaxHeap(dataArray);
		// 建立完成后dataArray[0],存储着最大值
		// 每次将0位置的最大值与最后一个元素做交换
		// 然后重建0位置的堆,使0位置的值仍然最大
		for (int i = dataArray.length - 1; i > 1; i--) {
			// 将0位置的最大值移到最后
			int temp = dataArray[0];
			dataArray[0] = dataArray[i];
			dataArray[i] = temp;
			heapSize--;
			MaxHeapify(dataArray, heapSize, 0);// 重建0位置的堆
		}
	}
	
	// 将数组建成最大堆
	private static void BuildMaxHeap(int[] dataArray) {
		// 从dataArray.length/2开始的结点都为叶子结点。叶子结点可以视为最大堆
		for (int i = dataArray.length >> 1; i >= 0 ; i--) {
			MaxHeapify(dataArray, dataArray.length, i);
		}		
	}
	
	// 使以index为下标的子树成为最大堆
	// heapSize:堆的长度
	private static void MaxHeapify(int[] dataArray, int heapSize, int index) {
		int left = index << 1; // 左儿子节点下标
		int right = left + 1; // 右儿子节点下标
		int largest = index; // 最大值下标,默认为父节点

		if (left < heapSize && dataArray[left] > dataArray[index]) {
			largest = left; // 左儿子值比较父节点大
		}
		if (right < heapSize && dataArray[right] > dataArray[largest]) {
			largest = right; // 右儿子值最大
		}
		if (largest != index) { // 如果最大节点不是父节点,则做交换,使父节点最大
			int temp = dataArray[index];
			dataArray[index] = dataArray[largest];
			dataArray[largest] = temp;
			MaxHeapify(dataArray, heapSize, largest);// 被交换后的儿子节点下面也要递归此过程
		}
	}
}


你可能感兴趣的:(堆排序)