排序算法之堆排序

基于堆的数据结构,形成了一种堆的排序算法,叫做堆排序。堆排序总的运行时间是o(N log N)

这个算法的主要问题在于使用了一个附加的数组,存储需求增加了一倍,因此这里采用一种回避的算法:在每次deletemin后堆缩小1,位于堆中的最后的单元可以用来存放刚刚删除的元素。

算法的主要逻辑思路:

1、创建堆数据结构;

2、删除位于根最小值(或者最大值);

3、重新构造堆的结构;

4、重复2和3的操作,直到堆中元素删除完成。

下面看代码实现:

package structures.arithmetic;

/**
 * 堆排序算法(寻找堆中最大值)
 */
public class BinarySort {

    /**
     *
     * @param i 代表堆中父节点的位置
     * @return 返回的是父节点中左子树的位置
     */
    private static int leftChild(int i){
        return 2 * i +1;
    }

    /**
     * 找出i位置的节点的值应该存放的位置
     * @param a 数组
     * @param i 堆中需要排序的数据的位置
     * @param n 堆的长度
     * @param <AnyType>
     */
    private static <AnyType extends Comparable<? super AnyType>> void percDown(AnyType[] a, int i, int n){

        int child = 0;
        AnyType tmp;
        for(tmp = a[i]; leftChild(i)<n; i=child){
            child = leftChild(i);
            //寻找出i位置2个子节点中比较大的值得位置
            if(child!=n-1&&a[child].compareTo(a[child+1])<0){
                child++;
            }

            if(tmp.compareTo(a[child])<0){
                a[i] = a[child];
            }else{
                break;
            }
        }

        a[i] = tmp;
    }

    public static <AnyType extends Comparable< ? super AnyType>> void heapSort(AnyType[] a){
        //将数组在二叉堆中排序
        for(int i=a.length/2-1; i>=0; i--){
            //这里取数组的长度的二分之一是因为后面的数据全部当做了子节点,不用构建二叉堆数据位置
            percDown(a, i, a.length);
        }
        for(int i=a.length-1;i>0;i--){
            //取出最大值,并放在数组的后面
            swapReferences(a,0,i);
            //重新构建二叉堆
            percDown(a, 0, i);
        }
    }

    /**
     * 将数组中元素的位置交换
     * @param a  数组
     * @param i  要交换的元素在数组中的位置
     * @param i1 要交换的元素在数组中的位置
     */
    private static <AnyType extends Comparable<? super AnyType>> void swapReferences(AnyType[] a, int i, int i1) {
        AnyType tmp = a[i];
        a[i] = a[i1];
        a[i1] = tmp;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值