-堆排序-

 

堆排序:就是一个不断调整最大堆/最小堆的过程。

最大值元素在堆顶,每拿出一个堆顶,就调整堆一次,时间复杂度是:n*logn,一次调整堆的时间复杂度是logn

/*
 * 堆排序
 */
public class HeapSort {
    @Test
    public  void heapC(){
        int[] arr = new int[]{1,2,3,4,5,6,1}; //arr下标从0~n-1
        // 根节点最后一个父节点的序号为,(arr.length-1)/2,向自己及自己的子树调整出最大根,
        for(int i=(arr.length-1)/2;i>=0;i--){
            //向自己及自己的子树调整出最大根
            adjust(arr,i);
        }
        //显示结果
        for(int i=0;i<arr.length;i++){
            System.out.println(" "+arr[i]);
        }
    }

    
    //k是当前待调整元素的下标
    public static void adjust(int arr[],int k){
        int temp = arr[k];
        // 从k的子树下标开始比较,找到比自己值大的子树下标,就交换,然后交换的位置继续比较其子树
        // 因为下标是从0开始的,所以其左子树和右子树下标是,2*(k+1)i-1和2*(k+1)    i=2*(i+1)-1 就是找其左子树
       for(int i = 2*(k+1)-1;i<arr.length;i=2*(i+1)-1){
            //先比较,如果右节点存在,且右节点大于左节点,就用右节点去交换
           if(i+1<arr.length && arr[i+1]>arr[i]){
               //与右节点比较,且交换,k值更新,i值更新
               if(temp<arr[i+1]){
                 arr[k] = arr[i+1];
                 arr[i+1] = temp;
                 k=i+1;
                 i++;
               }else { //大于最大的子节点,就不需要再调整
                   break;
               }
           //左节点大于右节点,
           }else if(temp<arr[i]){
               arr[k] = arr[i];
               arr[i] = temp;
               k=i;
           }
           else{
               break;
           }

       }
    }

}
package algothrim.sort;

import org.junit.Test;

/*
 * 堆排序
 */
public class HeapSort {
    @Test
    public  void heapC(){
        int[] arr = new int[]{0,1,2,3,4,5,6,1}; //arr有效数据下标从1~n-1
        // 根节点最后一个父节点的序号为,(arr.length-1)/2,向自己及自己的子树调整出最大根,
        int len = arr.length-2; //数组的长度

        //初始建堆
        for(int i=len/2; i>=1; i--){
            //向自己及自己的子树调整出最大根
            adjustDown(arr,i,len);
        }

        //堆排序: 这是一个大根堆,每出一个堆顶就与该堆的最后一个元素交换,所以最后是从小到大的顺序输出
        heapSort(arr,arr.length-2);
        //插入之前结果
        for(int i=1;i<arr.length;i++){
            System.out.print(" "+arr[i]);
        }
        System.out.println();
        //插入一个节点
        adjustUp(arr,arr.length-1);
        插入之后显示结果
        for(int i=1;i<arr.length;i++){
            System.out.print(" "+arr[i]);
        }

    }

    //k是当前待调整元素的下标,len是最后一个元素的下标+1
    public static void adjustDown(int arr[],int k,int len){
        arr[0] = arr[k];
        for(int i=2*k;i<=len;i*=2) {
            if (i < len && arr[i] < arr[i + 1])
                i++;
            if (arr[0] >= arr[i])
                break;
            else {
                arr[k] = arr[i];
                k = i;
            }
        }
        arr[k] = arr[0]; //被筛选节点的值放入最终位置
    }

    //堆排序:就是一个删除堆顶元素的过程,删除堆顶元素时,先将堆的最后一个元素与堆顶元素交换,然后进行向下调整
    //arr的有效数据是1~n-1
    public void heapSort(int arr[],int len){
        for (int i = len;i>0;i--){
            swap(arr,i,1); //输出堆顶元素,和堆底元素交换
            adjustDown(arr,1,i-1);
        }
    }

    public void swap(int a[],int i,int j){
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

    //插入堆顶元素,将元素进行向上调整
    public void adjustUp(int a[],int k){
        a[0] = a[k];
        int i=k/2;
        while(i>0 && a[i]<a[0]){
            a[k] = a[i];
            k = i;
            i=k/2; //继续向父节点比较
        }
        a[k] = a[0]; //将a[0]放到最终的位置
    }

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值