排序之堆排序

package csu.sort;
/**
 * 堆排序
 * 堆的定义:堆是一个完全,或近似完全的二叉树,堆顶元素的值大于左右孩子的值,左右孩子也需要满足这个条件;
 * 按照堆的定义,堆可以是大顶堆(maxHeap),或小顶堆(minHeap);
 * 一般用数组即可模拟二叉树,对于任意元素i,左孩子为2*i+1,右孩子为2*i+2;父节点为(i-1)/2
 * 时间复杂度: 平均:O(nlogn); 
 * 空间复杂度: O(1);
 */
import java.util.Arrays;
import java.util.Random;

public class HeapSortAsc {
    public void heapSort(int[] arr){
    	//先从最后一个非叶子节点向上调整,使得满足堆结构
    	for(int i=arr.length/2-1;i>=0;i--){
    		maxHeapAdjust(arr,i,arr.length-1);
    	}
    	//每次拿最后一个节点和第一个节点交换,然后调整堆;直到堆顶
    	for(int i=arr.length-1;i>0;i--){
    		int temp = arr[i];
    		arr[i] = arr[0];
    		arr[0] = temp;
    		maxHeapAdjust(arr,0,i);
    	}
    }
    /**
     * 调整堆
     * 把以i为跟节点的二叉树调整为堆
     * 这个完全二叉树就像一个金字塔,塔顶的小元素沿着树结构,往下沉降
     * 调整的结果是最大的元素在金字塔顶,然后把它从堆中删除(把它交换到堆尾,然后堆收缩一格);
     * 堆排序快的原因就是根据二叉树的特点,一个节点要沉降到合适的位置,只需要logn步;
     * 同时前期调整的结果(大小顺序)会被记录下来,从而加快后续的调整
     * @param arr
     * @param i
     * @param len
     */
    public void maxHeapAdjust(int[] arr,int i,int len){
    	int temp = arr[i];
    	int j = 2*i+1;//i的左孩子节点
    	while(j<len){
    		//从左右孩子中找出大的
    		//j+1为右孩子节点
    		if(j+1<len && arr[j+1]>arr[j]){
    			j++;
    		}
    		//找到合适的位置就不再找了
    		if(arr[j]<temp){
    			break;
    		}
    		//否则将较大的沿着树往上移动;
    		arr[i] = arr[j];
    		//i指向刚才的较大孩子
    		i=j;
    		//j指向新的左孩子节点
    		j= 2*i+1;
    	}
    	arr[i] = temp;
    }
    public static void main(String[] args) {
    	Random ran = new Random();
    	int[] arr = new int[20];
    	for(int i=0;i<20;i++){
    		arr[i]=ran.nextInt(100);
    	}
    	HeapSortAsc hsa = new HeapSortAsc();
    	hsa.heapSort(arr);
    	System.out.println(Arrays.toString(arr));
	}
}
//输出结果:[1, 4, 14, 26, 27, 28, 28, 32, 35, 40, 41, 45, 48, 57, 58, 64, 68, 79, 88, 95] 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值