堆排序

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法,它是选择排序的一种。先说 一下什么是堆。

二叉堆的定义:
堆分为大根堆和小根堆两种。对于一个小根堆,它是具有如下特性的一颗完全二叉树。

  1. 若树根结点存在左孩子,则根结点的值(或某个域的值)小于等于左孩子结点的值(或某个域的值);
  2. 若树根结点存在右孩子,则根结点的值(或某个域的值)小于等于右孩子结点的值(或某个域的值);
  3. 以左、右孩子为根的子树又各是一个堆;
    大根堆的定义于上述类似,只要把小于等于改为大于等于就行。

堆的存储:
一般都用数组来表示堆。
若array[0,…,n-1]表示一颗完全二叉树的顺序存储模式,则双亲节点指针和孩子结点指针之间的内在关系如下:

  任意一节点指针 i:父节点:i==0 ? null : (i-1)/2

           左孩子:2*i + 1

           右孩子:2*i + 2
堆应该满足以下需求:
1.小根堆:array[i] <= array[2*i + 1] 且 array[i] <= array[2*i + 2];
2.大根堆:array[i] >= array[2*i + 1] 且 array[i] >= array[2*i + 2];

大根堆排序

  1. 初始化操作:将arr[0,..,n-1]构造为初始堆;
  2. 每一趟排序的基本操作:将当前无序区的堆顶记录arr[0]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。
import java.util.Arrays;

public class MaxHeap {
    public static void main(String[] args) {
        int[] arr = {23,15,43,22,67,100,60,55,76};
        buildMaxHeap(arr);
        System.out.println(Arrays.toString(arr));
        heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void heapSort(int[] arr){
        //buildMaxHeap(arr); //为便于观察,测试中初始化成堆
        for(int i=arr.length-1; i>1; i--){
            int temp = arr[0];//堆顶元素和堆底元素交换,得到最大值
            arr[0] = arr[i];
            arr[i] = temp;
            adjust(arr,0,i);//调整
        }
    }
    public static void buildMaxHeap(int[] arr){
         //从最后一个节点array.length-1的父节点(array.length-1-1)/2开始,直到根节点0,反复调整堆
        for(int i=(arr.length-2)/2; i>=0; i--){
            adjust(arr, i, arr.length);
        }
    }
    private static void adjust(int[] arr, int n, int length) {
        int temp = arr[n];
        for(int i=2*n+1; i<length-1; i=2*i+1){//i为初始化节点n的左孩子
            if(i<length && arr[i]<arr[i+1]){//取节点较大的子节点的下标
                i++;//如果节点的右孩子的值>左孩子,取右孩子节点的下标
            }
            if(temp>=arr[i]){//如果根节点>=左右节点中较大的,不用调整
                break;
            }else{
                arr[n] = arr[i];//将左右子结点中较大值调整到父节点上
                n = i;//修改n值,以便继续向下调整
            }
        }
        arr[n] = temp;//被调整的结点的值放到孩子节点的位置
    }



}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值