我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java如何实现二叉堆、大顶堆和小顶堆

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java如何实现二叉堆、大顶堆和小顶堆

这篇文章将为大家详细讲解有关Java如何实现二叉堆、大顶堆和小顶堆,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

什么是二叉堆

二叉堆就是完全二叉树,或者是靠近完全二叉树结构的二叉树。在二叉树建树时采取前序建树就是建立的完全二叉树。也就是二叉堆。所以二叉堆的建堆过程理论上讲和前序建树一样。

什么是大顶堆、小顶堆

二叉堆本质上是一棵近完全的二叉树,那么大顶堆和小顶堆必然也是满足这个结构要求的。在此之上,大顶堆要求对于一个节点来说,它的左右节点都比它小;小顶堆要求对于一个节点来说,它的左右节点都比它大。

建堆

二叉堆建堆本质上和前序建堆差不多,只不过需要考虑的一点就是大小关系,这一点和二叉搜索树建树有点相似,所以可以得出结论,建树,本质上都是递归建树,只不过因为数据结构的大小要求不一样,需要的判断函数不一样,节点进入哪个位置也不一样。

大顶堆和小顶堆也分为稳定和不稳定的堆。稳定和不稳定指如果具备相同的值,那么他们的插入顺序应该和节点顺序一致。

程序实现

首先,定义出基本的堆结构

public class BinaryHeap {    private Integer value;    private BinaryHeap leftChild;    private BinaryHeap rightChild;}

建堆过程与建二叉树过程一致

public static BinaryHeap buildHeap(BinaryHeap binaryHeap, Integer value) {    if (Objects.isNull(binaryHeap)) binaryHeap = new BinaryHeap();    if (Objects.isNull(binaryHeap.getValue())) {        binaryHeap.setValue(value);        return binaryHeap;    }    if (Objects.isNull(binaryHeap.getLeftChild())) {        BinaryHeap binaryHeap1 = new BinaryHeap();        binaryHeap1.setValue(value);        binaryHeap.setLeftChild(binaryHeap1);    } else if (Objects.nonNull(binaryHeap.getLeftChild())) {        if (Objects.isNull(binaryHeap.getRightChild())) {            BinaryHeap binaryHeap1 = new BinaryHeap();            binaryHeap1.setValue(value);            binaryHeap.setRightChild(binaryHeap1);        } else {            // TODO: 2022/1/14 左右节点两种都不为null            if (checkNull(binaryHeap.getLeftChild())) buildHeap(binaryHeap.getLeftChild(), value);            else if (checkNull(binaryHeap.getRightChild())) buildHeap(binaryHeap.getRightChild(), value);            else buildHeap(binaryHeap.getLeftChild(), value);        }    }    return binaryHeap;}

主要原理就是如果当前节点的左节点为空,则把当前值放到左节点,如果左节点不为空,右节点为空,则把值放到右节点。如果左右节点都不为空,就将建树过程转移到下一层,如果左节点有为空的子节点,就转移给左节点,如果左节点没有为空的子节点,且右节点有为空的子节点,那么转移给右节点。如果左右节点都没有为空的子节点,那么也转移给左节点。

以序列2,3,4,5,9,6,8,7为例,按照该算法建立出来的二叉堆结构如下:

{    "value": 2,    "left_child": {        "value": 3,        "left_child": {            "value": 4,            "left_child": {                "value": 8,                "left_child": null,                "right_child": null            },            "right_child": {                "value": 7,                "left_child": null,                "right_child": null            }        },        "right_child": {            "value": 5,            "left_child": null,            "right_child": null        }    },    "right_child": {        "value": 1,        "left_child": {            "value": 9,            "left_child": null,            "right_child": null        },        "right_child": {            "value": 6,            "left_child": null,            "right_child": null        }    }}

建立大顶堆

大顶堆在建堆的基础上,有一个要求,根节点比左右子树的任何节点的值都大。那么建树的过程可以分为两步,对于每一个值,首先按照建树过程,会到二叉堆的最底部,然后通过不断的让自己与自己的根节点做比较,如果自己大于根节点,就交换自己与根节点的位置,递归回溯即可。

逻辑过程

Java如何实现二叉堆、大顶堆和小顶堆

假设现在红色节点组成的已经是一个大顶堆,现在新增了一个节点到这个二叉堆中,而且是比任意节点都大,那么黑色箭头将是该节点的行动路线,它会反复与父级比较,如果大于父级,则交换和父级的关系。

程序实现

public static BinaryHeap up(BinaryHeap father) {  if (Objects.nonNull(father.getLeftChild())) {    if (father.getValue() < father.getLeftChild().getValue()) {      int c = father.getValue();      father.setValue(father.getLeftChild().getValue());      father.getLeftChild().setValue(c);    }    up(father.getLeftChild());  }  if (Objects.nonNull(father.getRightChild())) {    if (father.getValue() < father.getRightChild().getValue()) {      int c = father.getValue();      father.setValue(father.getRightChild().getValue());      father.getRightChild().setValue(c);    }    up(father.getRightChild());  }  return father;}

该方法放在普通建树方法之后,就是大顶堆的建树方法了,总的方法如下:

public static BinaryHeap bigPush(BinaryHeap binaryHeap, Integer value) {    binaryHeap = buildHeap(binaryHeap, value);    up(binaryHeap);    return binaryHeap;}

还是以序列2,3,4,5,9,6,8,7为例,按照该算法建立出来的大顶堆结构如下:

{    "value": 9,    "left_child": {        "value": 8,        "left_child": {            "value": 7,            "left_child": {                "value": 2,                "left_child": null,                "right_child": null            },            "right_child": {                "value": 4,                "left_child": null,                "right_child": null            }        },        "right_child": {            "value": 3,            "left_child": null,            "right_child": null        }    },    "right_child": {        "value": 6,        "left_child": {            "value": 1,            "left_child": null,            "right_child": null        },        "right_child": {            "value": 5,            "left_child": null,            "right_child": null        }    }}

建立小顶堆

小顶堆与大顶堆类似

逻辑过程

Java如何实现二叉堆、大顶堆和小顶堆

过程与大顶堆一致,不过此时是比父级小就和父级交换。

程序实现

public static BinaryHeap down(BinaryHeap father) {    if (Objects.nonNull(father.getLeftChild())) {        if (father.getValue() > father.getLeftChild().getValue()) {            int c = father.getValue();            father.setValue(father.getLeftChild().getValue());            father.getLeftChild().setValue(c);        }        down(father.getLeftChild());    }    if (Objects.nonNull(father.getRightChild())) {        if (father.getValue() > father.getRightChild().getValue()) {            int c = father.getValue();            father.setValue(father.getRightChild().getValue());            father.getRightChild().setValue(c);        }        down(father.getRightChild());    }    return father;}

这个是向下走的过程,最终代码为:

public static BinaryHeap smallPush(BinaryHeap binaryHeap, Integer value) {    binaryHeap = buildHeap(binaryHeap, value);    down(binaryHeap);    return binaryHeap;}

以序列2,3,4,5,9,6,8,7为例,按照该算法建立出来的小顶堆结构如下:

{    "value": 1,    "left_child": {        "value": 3,        "left_child": {            "value": 4,            "left_child": {                "value": 8,                "left_child": null,                "right_child": null            },            "right_child": {                "value": 7,                "left_child": null,                "right_child": null            }        },        "right_child": {            "value": 5,            "left_child": null,            "right_child": null        }    },    "right_child": {        "value": 2,        "left_child": {            "value": 9,            "left_child": null,            "right_child": null        },        "right_child": {            "value": 6,            "left_child": null,            "right_child": null        }    }}

从堆顶取数据并重构大小顶堆

public static Integer bigPop(BinaryHeap binaryHeap) {    Integer val = binaryHeap.getValue();    if (binaryHeap.getLeftChild().getValue() >= binaryHeap.getRightChild().getValue()) {        binaryHeap.setValue(binaryHeap.getLeftChild().getValue());        BinaryHeap binaryHeap1 = mergeTree(binaryHeap.getLeftChild().getLeftChild(), binaryHeap.getLeftChild().getRightChild());        up(binaryHeap1);        binaryHeap.setLeftChild(binaryHeap1);    } else {        binaryHeap.setValue(binaryHeap.getRightChild().getValue());        BinaryHeap binaryHeap1 = mergeTree(binaryHeap.getRightChild().getLeftChild(), binaryHeap.getRightChild().getRightChild());        up(binaryHeap1);        binaryHeap.setRightChild(binaryHeap1);    }    return val;}public static Integer smallPop(BinaryHeap binaryHeap) {    Integer val = binaryHeap.getValue();    if (binaryHeap.getLeftChild().getValue() <= binaryHeap.getRightChild().getValue()) {        binaryHeap.setValue(binaryHeap.getLeftChild().getValue());        BinaryHeap binaryHeap1 = mergeTree(binaryHeap.getLeftChild().getLeftChild(), binaryHeap.getLeftChild().getRightChild());        down(binaryHeap1);        binaryHeap.setLeftChild(binaryHeap1);    } else {        binaryHeap.setValue(binaryHeap.getRightChild().getValue());        BinaryHeap binaryHeap1 = mergeTree(binaryHeap.getRightChild().getLeftChild(), binaryHeap.getRightChild().getRightChild());        down(binaryHeap1);        binaryHeap.setRightChild(binaryHeap1);    }    return val;}

取出来之后,需要重新调用down或者up函数。以构建小顶堆,取出五次后的结果

public static void main(String[] args) {        int[] a = new int[]{2, 3, 1, 4, 5, 9, 6, 8, 7};        BinaryHeap binaryHeap = new BinaryHeap();        for (int i = 0; i < a.length; i++) {            binaryHeap = smallPush(binaryHeap, a[i]);        }        System.out.println(Json.toJson(smallPop(binaryHeap)));        System.out.println(Json.toJson(smallPop(binaryHeap)));        System.out.println(Json.toJson(smallPop(binaryHeap)));        System.out.println(Json.toJson(smallPop(binaryHeap)));        System.out.println(Json.toJson(smallPop(binaryHeap)));        System.out.println(Json.toJson(binaryHeap));    }

取完后的小顶堆为:

{    "value": 6,    "left_child": {        "value": 7,        "left_child": {            "value": 8,            "left_child": null,            "right_child": null        },        "right_child": null    },    "right_child": {        "value": 9,        "left_child": null,        "right_child": null    }}

关于“Java如何实现二叉堆、大顶堆和小顶堆”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java如何实现二叉堆、大顶堆和小顶堆

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java如何实现二叉堆、大顶堆和小顶堆

这篇文章将为大家详细讲解有关Java如何实现二叉堆、大顶堆和小顶堆,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。什么是二叉堆二叉堆就是完全二叉树,或者是靠近完全二叉树结构的二叉树。在二叉树建树时采取前序建
2023-06-29

Java 堆排序实例(大顶堆、小顶堆)

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序的平均时间复杂度为Ο(nlogn) 。算法步骤:1. 创建
2023-05-30

Java利用完全二叉树创建大根堆和小根堆

大根堆是每个结点的值不大于他的父亲结点的值;小根堆是每个结点的值不小于他的父亲结点的值。本文将利用完全二叉树创建大根堆和小根堆,感兴趣的可以了解一下
2022-11-13

Java语言如何实现二叉堆的打印

这篇文章将为大家详细讲解有关Java语言如何实现二叉堆的打印,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树)。二叉堆有两种:最
2023-05-30

最小二叉树堆排序怎么利用java 实现

这篇文章给大家介绍最小二叉树堆排序怎么利用java 实现,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。最小二叉堆定义: 二叉堆是完全二元树或者是近似完全二元树,最小二叉堆是父结点的键值总是小于或等于任何一个子节点的键值
2023-05-31

Java语言如何实现最大堆

这篇文章将为大家详细讲解有关Java语言如何实现最大堆,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。最大堆最大堆的特点是父元素比子元素大,并且是一棵完全二叉树。data[1]开始存,data[0]空着不用
2023-05-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录