HeapSort

算法描述开始:

①堆排序算法:假设已经建立好了最大堆,将堆顶元素跟最后一个元素交换,然后将堆的长度减1,此时堆可能已经不是最大堆了,所以需要将减1之后的堆变成最大堆,即始终保持待排序的堆是最大堆,直到堆的大小变为1,结束。

②保持最大堆(递归体):假设左右子树都是最大堆,比较根元素跟左右孩子的大小,若根元素小于左孩子或者右孩子的大小,调整它们的值,使得根元素最大。调整后,左子树或者右子树已经不是最大堆了,递归调用,让调整的子树变成最大堆。

③建堆:由于堆是一个完全二叉树,所以从第a.length/2+1个元素开始到最后一个元素,都是叶节点,从a.length/2到第一个元素都是父节点,于是可以从第a.length/2到第一个元素开始,让它们保持最大堆,即调用步骤②。

算法描述结束。

下面用Java代码实现上述描述:

 

public class HeapSort {
	/**堆排序算法步骤:
	 * ①让数组保持最大堆性质
	 * ②建立最大堆
	 * ③堆排序
	 */
	public static int heapSize;
	/**
	 * 
	 * @param i
	 * @return 父节点编号
	 */
	public static int parentId(int i){
		return i/2;
	}
	/**
	 * 
	 * @param i
	 * @return 左孩子节点编号
	 */
	public static int leftChildId(int i){
		return 2*i;
	}
	/**
	 * 
	 * @param i
	 * @return 右孩子节点编号
	 */
	public static int rightChildId(int i){
		return 2*i +1;
	}
	/**
	 * 保持最大堆的性质
	 * ①比较左(右)孩子元素跟父节点元素的大小,调整它们大小,使得父节点元素最大
	 * ②使调整的左(右)子树也保持最大堆性质
	 * @param array
	 * @param i
	 */
	public	static void maxHeapity(int []array,int i){
		int left = leftChildId(i);
		int right= rightChildId(i);
		int largest ;
		//比较左、父、右节点元素,获得最大元素的下标
		if(left < heapSize && array[left] > array[i]){
			largest = left;
		}else{
			largest = i;
		}
		if(right < heapSize && array[right] > array[largest]){
			largest = right;
		}
		if(largest == i){
			return ;
		}else{
			int temp = array[i];
			array[i] = array[largest];
			array[largest] = temp;
			maxHeapity(array,largest);
		}
	}
	/**
	 * 根据数组元素建立最大堆
	 * @param array
	 */
	public static void buildMaxHeap(int []array){
		for(int i = array.length/2;i>=0;i--){
			maxHeapity(array,i);
		}
	}
	/**
	 * 使用堆实现元素递增排序
	 * @param array
	 */
	public static void heapSort(int[] array){
		buildMaxHeap(array);
		for(int i =array.length -1;i>=1;i--){
			int temp = array[0];
			array[0] = array[i];
			array[i] = temp;
			heapSize --;
			maxHeapity(array, 0);
		}
	}
	public static void main(String[] args){
		int[] array = {18,25,34,9,16,20,41,43,56,26};
		heapSize = array.length;
		heapSort(array);
		for(int i=0;i<array.length;i++){
			System.out.print(array[i]+" ");
		}
	}
}

程序运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值