堆排序

                                                   堆排序

堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。

用简单的公式来描述一下就是:

大顶堆:arr[i]>=arr[2i+1] && arr[i]>=arr[2i+2]

小顶堆:arr[i]<=arr[2i+1] && arr[i]<=arr[2i+2]

思路(大顶堆):

  1. 将给定的待排序序列(R1,R2,...,Rn)构建成大顶堆,此堆为初始的无序区。
  2. 将堆顶元素R[1]与无序区的最后一个元素R[n]交换,此时得到新的无序区(R1,R2,...,Rn-1)和新的有序区(Rn)。
  3. 由于交换后新的堆顶R[1]可能违反大顶堆的性质,因此需要对当前无序区(R1,R2,...,Rn-1)调整为新的大顶堆,然后再次将RR[1]与无序区的最后一个元素R[n-1]交换,得到新的无序区(R1,R2,...,Rn-2)和新的有序区(Rn-1,Rn)。
  4. 不断重复此过程直到无序区还剩一个元素,则整个过程完成。

package 堆排序;

 

import java.util.Arrays;

 

public class Main{

    public static void main(String[] args) {

        //定义一个数组

        int[] arr = {2,34,54,65,1,3,3,34,23};

 

        //调用方法,堆排序

        heapSort(arr);

 

        //打印结果

        System.out.println(Arrays.toString(arr));

    }

 

    //堆排序入口方法

    private static void heapSort(int[] arr) {

        //将数组初始化为最大堆

        for(int i=arr.length/2-1;i>=0;i--){

            adjust(arr,i,arr.length-1);//调用方法,调整最大堆

        }

 

        //j为无序数组最后一个元素的角标位置,从arr.length-1开始,到无序数组只剩一个元素

        for(int j=arr.length-1;j>0;j--){

            //将最大堆的第一个元素和最后一个元素交换

            int tmp = arr[0];

            arr[0] = arr[j];

            arr[j] = tmp;

            //重新调整最大堆

            adjust(arr,0,j-1);

        }

    }

 

    //调整最大堆

    //arr:待排序数组  i:要调整堆的堆顶元素角标  j:无序数组最后一个元素的角标

    private static void adjust(int[] arr, int i, int j) {

        for(int k=2*i+1;k<=j;k=2*k+1){//k为左子节点的角标

            //找左、右子节点中的最大值

            if(k<j&&arr[k]<arr[k+1]){

                k++;

            }

            //如果左、右子节点中的最大值大于父节点,交换位置

            if(arr[k]>arr[i]){

                int t = arr[k];

                arr[k] = arr[i];

                arr[i] = t;

                i = k;//重新调整堆顶元素角标位置

            }else{

                break;

            }

        }

    }

}

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值