前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java常见排序算法详解——堆排序

Java常见排序算法详解——堆排序

作者头像
Demo_Yang
发布2019-04-18 17:05:45
8130
发布2019-04-18 17:05:45
举报
文章被收录于专栏:yang0rangeyang0range
转载请注明出处:https://cloud.tencent.com/developer/article/1415362
概念
二叉树

要了解堆首先得了解一下二叉树,在计算机科学中,二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。

二叉树的每个结点至多只有二棵子树(不存在度大于 2 的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第 i 层至多有 2i - 1 个结点;深度为 k 的二叉树至多有 2k - 1 个结点;对任何一棵二叉树 T,如果其终端结点数为 n0,度为 2 的结点数为 n2,则n0 = n2 + 1。

树和二叉树的三个主要差别:

树的结点个数至少为 1,而二叉树的结点个数可以为 0

树中结点的最大度数没有限制,而二叉树结点的最大度数为 2

树的结点无左、右之分,而二叉树的结点有左、右之分

二叉树又分为完全二叉树(complete binary tree)和满二叉树(full binary tree)

如图:

满二叉树:一棵深度为 k,且有 2k - 1 个节点称之为满二叉树

完全二叉树:深度为 k,有 n 个节点的二叉树,当且仅当其每一个节点都与深度为 k 的满二叉树中序号为 1 至 n 的节点对应时,称之为完全二叉树

堆(二叉堆)可以视为一棵完全的二叉树,完全二叉树的一个“优秀”的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示(普通的一般的二叉树通常用链表作为基本容器表示),每一个结点对应数组中的一个元素。

如下图,是一个堆和数组的相互关系

二叉堆一般分为两种:最大堆和最小堆。

最大堆:

最大堆中的最大元素值出现在根结点(堆顶)

堆中每个父节点的元素值都大于等于其孩子结点(如果存在)

最小堆:

最小堆中的最小元素值出现在根结点(堆顶)

堆中每个父节点的元素值都小于等于其孩子结点(如果存在)

原理
  1. 最大堆调整(Max_Heapify):从堆的倒数第一个非叶子节点作调整,使得子节点永远小于父节点。没有必要从叶子节点开始,叶子节点可以看作是已符合堆特点的节点。
  2. 创建最大堆(Build_Max_Heap):将堆所有数据重新排序
  3. 堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整。 图解:列如我们有原始数字2 10 9 5 6 1 下面我们用堆排序排序 原始为:

第一次:

第二次

我们得到了

代码实现:

代码语言:javascript
复制
 /**
     * 堆排序的主要入口方法,共两步。
     */
    public void sort() {
        /*
         *  第一步:将数组堆化
         *  beginIndex = 第一个非叶子节点。
         *  从第一个非叶子节点开始即可。无需从最后一个叶子节点开始。
         *  叶子节点可以看作已符合堆要求的节点,根节点就是它自己且自己以下值为最大。
         */
        int len = array.length - 1;
        int beginIndex = (len - 1) >> 1;
        for (int i = beginIndex; i >= 0; i--)
            maxHeapify(i, len);
        /*
         * 第二步:对堆化数据排序
         * 每次都是移出最顶层的根节点A[0],与最尾部节点位置调换,同时遍历长度 - 1。
         * 然后从新整理被换到根节点的末尾元素,使其符合堆的特性。
         * 直至未排序的堆长度为 0。
         */
        for (int i = len; i > 0; i--) {
            swap(0, i);
            maxHeapify(0, i - 1);
        }
    }

    private void swap(int i, int j) {
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    /**
     * 调整索引为 index 处的数据,使其符合堆的特性。
     *
     * @param index 需要堆化处理的数据的索引
     * @param len 未排序的堆(数组)的长度
     */
    private void maxHeapify(int index, int len) {
        int li = (index << 1) + 1; // 左子节点索引
        int ri = li + 1;           // 右子节点索引
        int cMax = li;             // 子节点值最大索引,默认左子节点。
        if (li > len) return;      // 左子节点索引超出计算范围,直接返回。
        if (ri <= len && array[ri] > array[li]) // 先判断左右子节点,哪个较大。
            cMax = ri;
        if (array[cMax] > array[index]) {  //若“<”这是从大到小
            swap(cMax, index);      // 如果父节点被子节点调换,
            maxHeapify(cMax, len);  // 则需要继续判断换下后的父节点是否符合堆的特性。
        }
    }
算法系列:

冒泡排序

选择排序

直接插入排序

二分插入排序

希尔排序

堆排序

完整代码:

Java和Kotlin代码我均放在了GitHub上,欢迎Star!

GitHub地址:https://github.com/yang0range/MyAlgorithm

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.04.11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 转载请注明出处:https://cloud.tencent.com/developer/article/1415362
  • 概念
    • 二叉树
      • 原理
      • 算法系列:
      • 完整代码:
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档