java 堆排序

最近在看算法导论,学习了堆排序。今天特以记笔记的方式,来讲下堆排序的过程。

首先我们知道,堆分为最大堆跟最小堆两种。在最大堆中,最大堆性质是指除了根以为的所有节点 i 都要满足:

A[PARENT(i)] >=A[i]

也就是说,某个结点的值至多与其父结点一样大。因此,堆中的最大元素存放在根结点中;并且在任一子树中,该子树所包含的所有结点的值都不大于该孩子跟结点的值。最小堆正好相反。


先说下,整个排序的步骤:

1.先找到父结点,左结点,右结点三个之间最大的,然后跟父结点交换。保证父结点是最大的。

2.然后就是建堆的过程。

3.然后就是排序了。

下面就按部就班的一步一步来:

1、

先将父结点变成最大的。

比如像这样的二叉树的某一部分。最终的结果是2 和5掉了一个位置。那怎样用代码来解决呢。如下:

	//将父节点跟子节点比较,使得父节点是最大的,然后,将交换的节点,继续此操作
	private void ExchangeLagest(int array[],int heapSize,int index){
		int l=2*index+1;//左节点
		int r=2*index+2;//右节点
		int lagest=index;
		if(l<heapSize && array[l]>array[index]){ //判断左节点是否大于父节点,如果大于,就交换
			lagest=l;
		}
		if(r<heapSize && array[r]>array[lagest]){//判断右节点是否大于父节点,如果大于,就交换
			lagest=r;
		}
		if(lagest!=index){
			int temp=array[lagest];
			array[lagest]=array[index];
			array[index]=temp;
			ExchangeLagest(array, heapSize, lagest);//这边递归下,防止交换之后的节点影响下面的节点
		}
	}
下面就是第二步了,建堆的过程。

2、

我们知道堆可以看成是一个完全二叉树,那么在数组A[n/2+1....n]中的结点都是树的叶结点,也就是说每一个结点都可以看成只包含一个元素的堆。那么就相当于是这个堆已经是建好的,我们需要对 A[n/2....1] 从下往上的建堆。

那么好,通过下面代码就可以实现建堆的过程了

private void heap(int []array){
		/*
		 * 这里从数组长度的一半开始,因为,在大根堆中,一半之后,都是叶子节点,没有子节点
		 * 所以在建堆得过程中,不需要考虑
		 */
		for(int i=array.length/2;i>=0;i--){
			ExchangeLagest(array, array.length, i);
		}
		System.out.print("建过堆的数组:");
		for(int i=0;i<array.length;i++){
			System.out.print(array[i]);
		}
	}
这里就是,对length/2 到0 进行一个遍历,把每一个结点都进行步骤一的操作。

最后一步就是排序了。

3、

这里的排序就是,我们知道根结点已经是最大的了,让它跟最后一个结点交换数据,可以让该元素放到正确的位置。这时候,我们从堆中去掉结点n(这一操作可以通过减少heapSize的值来实现),剩余的结点中,原来根的孩子结点仍然是最大堆,而新的根结点可能会违背最大堆的性质。为了维护这一性质,我们要for循环重复建堆的过程。代码如下:

public void sort(){
		int array[]={4,8,1,9,5,0,3,6,2};
		System.out.print("原数组:");
		for(int i=0;i<array.length;i++){
			System.out.print(array[i]);
		}
		System.out.println();
		heap(array);
		for(int i=array.length-1;i>=1;i--){
			int temp=array[0];
			array[0]=array[i];
			array[i]=temp;
			ExchangeLagest(array, i, 0);
		}
		System.out.println();
		System.out.print("排序过后数组:");
		for(int i=0;i<array.length;i++){
			System.out.print(array[i]);
		}
	}
以上就是完成的堆排序的过程了。

运行结果如下:

再给大家贴一个草图,画的不是很好,见谅:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值