排序总结[4]_堆排序

这一篇介绍堆排序,堆排序需要具有背景知识二叉堆。

一、二叉堆(优先队列)

二叉堆是一种最常用的优先队列。

  1. 堆的性质:

    1.1 结构性质:堆是一颗完全二叉树,注意完全二叉树指的是除最底层外其他都是完全被填满的,对底层元素从左到右依次填入(可以不填满);
    1.2 堆序性质:以小堆为例,最小元素肯定在根上,而且每个子树也是一个小堆即任意节点的值小于其所有的后裔节点值。

  2. 完全二叉树的性质:

    完全二叉树可以用一个数组直接表示,类似层序遍历的结果
    对于数组中任一位置i上的元素,其父节点位置(i-1)/2,左子树位置:2i+1,右子树位置:2i+2

  3. 堆核心操作:

    3.1 上滤:插入一个新元素,先放在最底部,然后一步一步的和其父节点判断交换,最后到达其正确的位置上去的过程;
    3.2 下滤:一般根是最小的,是我们的目标,可是取走根之后留下一个空穴怎么办呢?取子节点值较小的放入空穴中,而且为保证每个子树也是小堆,移上去的节点所在子树也要下滤调节。

二、堆排序过程

基本思想:将待排数组看做一个完全二叉树,先建大堆(Build Heap),然后交换根元素和最后一个元素,再从根开始进行调节保持大堆特性,一直持续该步骤直到最后不需要交换为止。

时间复杂度:O(N+NlogN)=O(NlogN),(大O计法的话N可以省略)(最好、最坏和平均都是O(N*logN))
稳定性:不稳定

参考代码
//堆排序
void heapSort(int[] arr){
    if(arr==null)throw new NullPointerException();
    if(arr.length<=1)return;

    //Build Heap
    for(int i=arr.length/2;i>=0;--i){
        percDown(arr,i,arr.length);
    }

    //Swap And PercDown
    for(int i=arr.length-1;i>0;--i){
        swap(arr,0,i);
        percDown(arr,0,i);
    }
}
/**
 * 交换数组元素
 */
void swap(int[] arr,int i,int j){
    int tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}

/**
 * 下滤操作 
 */
void percDown(int[] arr,int i,int n){
    int child;
    int tmp;
    for(tmp=arr[i];2*i+1<n;i=child){ //subtree also need percdown
        child = 2*i+1;
        if(child!=n-1 && arr[child+1]>arr[child])
            child++;//find bigger value for swap
        if(tmp<arr[child])
            arr[i]=arr[child];
        else
            break;
    }
    arr[i] = tmp;
} 

转载于:https://www.cnblogs.com/lhyblog/p/5895607.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值