堆排序总结

前言

堆结构算是一种比较有难度的排序算法,如果大家看了这篇文章理解不了的话建议看一下视频,有些东西可能我描述的不是那么清楚。

1. 定义

堆排序(Heapsort )是利用堆这种数据结构所设计的一种排序算法。

2.堆的定义

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

以大顶堆为例,下图是大顶堆的图
在这里插入图片描述

我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子:

095
194
266
375
463
533
622
755
844
911

从上面的图中,我们可以总结出规律
对于某1个节点i,它的父节点(i-1)/2
对于某1个节点i,它的左孩子2i+1
对于某1个节点i,它的右孩子2
i+2
最后一个非叶子节点为(arr.length/2-1)(忽略小数点)

3.堆排序的思路

以大顶堆为例
(1)根据初始数组去构造初始堆(可以看成一个完全二叉树)。
(2)每次交换第一个和最后一个元素,输出最后一个元素(最大值),然后把剩下元素重新调整为大根堆,再进行交换第一个元素和最后一个元素,再调整大顶堆,重复执行,直到整个数组排序完成。

4.代码实现(大顶堆为例)

import java.util.Arrays;

public class Heapsort {
    public static void main(String[] args) {
        int[] arr = {3,2,1,4,6,77,22,11,22};
        heapsort(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void heapsort(int[] arr){
        //建初始堆
        for (int i = arr.length/2-1;i >= 0; i--){
            heapify(arr, i, arr.length-1);
        }
        //堆排序的过程
        for (int i = arr.length - 1; i > 0; i--){
            swap(arr,0,i);
            heapify(arr,0,i-1);
        }
    }

    //把一个非堆结构变成堆结构
    public static void heapify(int[] arr, int i, int last_index){
        int max = i;
        if (2*i+1 <= last_index && arr[max] < arr[2*i+1]){
            //记录最大值节点
            max = 2*i+1;
        }
        if (2*i+2 <= last_index && arr[max] < arr[2*i+2]){
            //记录最大值节点
            max = 2*i+2;
        }
        if (max != i){
            swap(arr,i,max);
            heapify(arr, max, last_index);
        }
    }

    //交换
    public static void swap(int[] arr, int i, int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

5.算法特点

算法稳定性:不稳定,因为在堆顶和堆底交换的时候两个相等的记录在序列的相对位置可能发生变化。
时间复杂度:O(n+nlog2^n) - O(nlog2^n)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十三豆啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值