Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >(JAVA)浅入数据结构 “堆” - 实现和理论

(JAVA)浅入数据结构 “堆” - 实现和理论

原创
作者头像
唐僧洗头爱飘柔
发布于 2024-10-09 02:23:27
发布于 2024-10-09 02:23:27
1600
举报

1. 堆

1.1 堆的定义

堆是计算机科学中一类特殊的数据结构的统称,堆通常可以被看做是一棵完全二叉树的数组对象

1.1.1 堆的特性

  1. 它是完全二叉树,除了树的最后一层节点不需要是满的,其他的每一层从左到右都是满的,如果最后一层节点不是满的,那么要求左满右不满
  1. 它通常用数组来实现
    • 具体方法就是将二叉树的节点按照层级顺序放入数组汇总,根节点在位置1,它的子节点在位置2和3,而子节点的子节点则分别在位置4,5,6和7,以此类推

如果一个节点的位置为k,则它的父节点的位置为k/2,而它的两个子节点的位置则分别是2k2k+1

  • 这样在不使用指针的情况下,我们也可以通过计算数组的索引在树中上下移动:

a[k]向上一层,就让k等于k/2

向下一层就让k等于2k2k+1

  1. 每个节点都大于等于它的两个子节点。

这里要注意堆中仅仅规定了每个节点大于等于它的两个子节点,但这两个子节点的顺序并没有做规定,跟二叉查找树是有区别的。

1.2 堆的API设计

类名

Heap<T extends Comparable<T>>

构造方法

Heap(int capacity):创建容量为caparity的Heap对象

成员方法

  1. private boolean less(int i,int j):判断堆中索引i处的元素是否小于索引j处的元素 2. private void exch(int i,int j):交换堆中i索引和j索引处的值 3. public T delMax():删除堆中最大的元素,并返回这个最大元素 4. public void insert(T t):往堆中插入一个元素 5. private void swim(int k):使用上浮算法,使索引k处的元素能在堆中处于一个正确的位置 6. private void sink(int k):使用下沉算法,使索引k处的元素能子啊堆中处于一个正确的位置

成员变量

  1. private T[] items:用来存储元素的数组 2. private int N:记录堆中元素的个数

1.3 堆的实现

1.3.1insert插入方法的实现

堆是使用数组完成数据元素的存储的,由于数组的底层是一串连续的内存地址,所以我们要往堆中插入数据。

我们只能往数组中从索引0处开始,以此往后存放数据,但是堆汇总堆元素的顺序是有要求的,每一个节点的数据要大于等于它的两个子节点的数据,所以每次插入一个元素都会使得堆中的数据顺序变乱,这个时候我们就需要通过一些方法让刚才插入的这个数据放入到合适的位置。

如果往堆中新插入元素,我们只需要不断的比较新节点a[k]和它的父节点a[k/2]的大小,如何根据完成数据元素的交换,就可以完成堆的有序调整

1.3.2 delMax删除最大元素方法的实现

由堆的特性可知,所以1处的元素,也就是根节点就是最大的元素,当我们把根节点的元素删除后,需要由一个新的根节点出现,这时我们可以暂时把队中最后一个元素放到所以1处,充当根节点,但是它右可能不满足堆的有序性需求,这个时候我们就需要通过一些方法,让这个新的根节点放入到合适的位置。

实现代码:

代码语言:java
AI代码解释
复制
package com.renexdemo.heap;

// 堆
public class Heap<T extends Comparable<T>> {
    private T[] items;
    private int N;

    // 初始化构造
    public Heap(int capacity) {
        this.items = (T[]) new Comparable[capacity+1];
        this.N = 0;
    }

    // 判断堆中i索引值是否小于索引j处的值
    private boolean less(int i,int j){
        return items[i].compareTo(items[j]) < 0;
    }

    // 交换堆中i和j索引的值
    private void exch(int i,int j){
        T temp = items[i];

        items[i] = items[j];
        items[j] = temp;
    }

    // 删除最大值-并返回该值
    public T delMax(){
        T max = items[1];

        // 交换元素,让完全二叉树最右侧的元素变为临时根节点
        exch(1,N);

        // 最大索引处的元素删除掉
        items[N] = null;

        // 元素个数-1
        N--;

        // 对堆重新排序
        sink(1);

        return max;
    }

    // 往堆中插入一个元素
    public void insert(T t){
        items[++N] = t;
        swim(N);
    }

    //上浮算法
    private void swim(int k){
        // 通过循环,不断的比较当前节点的值和父节点的值,如果发现父节点的值比当前节点的值小,则交换位置
        while (k>1){
            // 比较当前节点和父节点
            if (less(k/2,k)){
                exch(k/2,k);
            }
            k = k/2;
        }
    }

    // 下沉算法
    private void sink(int k){
        // 通过循环不断的对比当前k节点和其子节点2*k以及2k+1的元素大小,如果当前节点小,则需要交换位置

        // 若是左子节点大于最大索引,那么结束循环
        while (2*k<=N){
            // 获取当前节点的子节点的较大节点
            int max;// 记录较大节点所在的索引

            // 比较最大值
            if (2*k+1 <= N){
                if (less(2*k,2*k+1)){
                    max=2*k+1;
                }else {
                    max = 2*k;
                }
            }else {
                max = 2*k;
            }


            // 比较当前节点和较大节点的值
            if (!less(k,max)){
                break;
            }

            // 交换k索引处的值和max索引处的值
            exch(k,max);

            // 变换k的值
            k = max;

        }

    }
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java数据结构与算法解析(十三)——优先级队列
在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理次高的对象。最简单的一个例子就是,在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话。
老马的编程之旅
2022/06/22
4270
Java数据结构与算法解析(十三)——优先级队列
数据结构----二叉堆和优先权队列
堆有序:当一棵二叉树的每个结点都大于等于它的两个子结点时,它被称为堆有序。根结点是堆有序的二叉树中的最大节点。 二叉堆:二叉堆是一组能够用堆有序的完全二叉树排序的元素,并在数组中按层级存储(不使用数组的第一个位置)。 二叉堆可以使用数组或者二叉树实现,在这里使用数组实现。在数组中,根结点放置在下标为1的空间内;下标k的结点的父结点的下标为⌊k⌋,它的两个子结点的下标为2k和2k+1.  堆的实现: 构造堆的过程中,肯定会用到比较方法和交换方法: //比较方法 private boolean less(int
SuperHeroes
2018/05/30
5310
【数据结构与算法】堆
,总的交换次数为 $$ \begin{aligned} & 4 * 0 + 2 * 1 + 1 * 2 \
程序员波特
2024/09/27
830
【数据结构与算法】堆
图文详解二叉堆,实现优先级队列
二叉堆(Binary Heap)没什么神秘,性质比二叉搜索树 BST 还简单。其主要操作就两个,sink(下沉)和swim(上浮),用以维护二叉堆的性质。其主要应用有两个,首先是一种排序方法「堆排序」,第二是一种很有用的数据结构「优先级队列」。
灵魂画师牧码
2019/08/02
1.7K0
【数据结构】核心数据结构之二叉堆的原理及实现
互联网小阿祥
2023/05/28
8000
【数据结构】核心数据结构之二叉堆的原理及实现
【算法】堆排序学习笔记
根据文章内容总结,该文章介绍了一种基于C++实现的堆排序算法。首先介绍了堆排序算法的基本原理和步骤,然后详细展示了如何实现堆排序算法。该算法的时间复杂度为O(nlogn),是一种高效的排序算法。
啦啦啦321
2018/01/03
1.1K0
【算法】堆排序学习笔记
算法和数据结构:堆排序
在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理次高的对象。最简单的一个例子就是,在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话。
yaphetsfang
2020/07/30
7110
算法和数据结构:堆排序
《一文说透数据结构》系列之什么是堆?看这一篇就够了
本文将首先介绍什么是堆,然后介绍了堆的插入和删除操作,最后给出了堆的代码实现,并进行了测试。
乔戈里
2020/02/21
4890
《一文说透数据结构》系列之什么是堆?看这一篇就够了
数据结构+算法(第10篇)叉堆“功夫熊猫”的速成之路
上一篇文章《菜鸟也能“种”好二叉树!》提到:树是一种分层分类的数据结构,用途是查找和排序。而与查找和排序密切相关的就是求最值(最大值或者最小值)。今天我们就来介绍一个与最值相关的数据结构——二叉堆。
用户5224393
2019/06/05
8030
数据结构+算法(第10篇)叉堆“功夫熊猫”的速成之路
数据结构小记【Python/C++版】——堆结构篇
完全二叉树的结构特点是,除了最后一层,其他层的节点数都是满的,最后一层的节点靠左排列。
Coder-ZZ
2023/02/23
2930
数据结构小记【Python/C++版】——堆结构篇
【数据结构】堆篇
普通的二叉树是不适合用数组存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。实现中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统的虚拟进程地址空间的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。
Yui_
2024/10/16
1170
【数据结构】堆篇
堆排序实现及应用
堆排序(Heapsort)是指利用堆这样的数据结构所设计的一种排序算法。
全栈程序员站长
2022/07/10
3800
堆排序实现及应用
数据结构 - 堆(Heap)
数据结构 - 堆(Heap) 1.堆的定义 堆的形式满足完全二叉树的定义: 若 i < ceil(n/2) ,则节点i为分支节点,否则为叶子节点 叶子节点只可能在最大的两层出现,而最大层次上的叶子节点都依次排列在该层最左侧的位置上 如果有度为1的节点,那么只可能有一个,且该节点只有左孩子 根据堆定义的不同,分为大根堆和小根堆: 大根堆每个节点的值都大于其子节点的值 小根堆每个节点的值都小于其子节点的值 除此之外还有一个重要的内容: 单节点也符合堆的特质 2.堆的初始化 堆的初始化可以可以分为如下
Kindear
2020/09/28
5360
数据结构 - 堆(Heap)
前端学数据结构 - 堆(Heap)
堆都能用树来表示,并且一般树的实现都是利用链表。 而二叉堆是一种特殊的堆,它用完全二叉树表示,却可以利用数组实现。
JSCON简时空
2020/03/31
1.3K0
前端学数据结构 - 堆(Heap)
Java数据结构和算法(十四)——堆
  在Java数据结构和算法(五)——队列中我们介绍了优先级队列,优先级队列是一种抽象数据类型(ADT),它提供了删除最大(或最小)关键字值的数据项的方法,插入数据项的方法,优先级队列可以用有序数组来实现,这种实现方式尽管删除最大数据项的时间复杂度为O(1),但是插入还是需要较长的时间 O(N),因为每次插入平均需要移动一半的数据项,来保证插入后,数组依旧有序。   本篇博客我们介绍另外一种数据结构——堆,注意这里的堆和我们Java语言,C++语言等编程语言在内存中的“堆”是不一样的,这里的堆是一种树,由它
IT可乐
2018/03/30
9500
Java数据结构和算法(十四)——堆
数据结构之堆
有没有更优的数据结构?使用堆,可以使得获取最大值的时间复杂度为O(1)、删除最大值和添加元素的时间复杂度为O(logn)。
崔笑颜
2020/07/03
4700
数据结构--堆的深度解析
堆(Heap)是一种非常重要的非线性数据结构,广泛应用于各种算法和问题解决中,如优先队列、堆排序、Top-k 问题等。本文将深入解析堆的定义、类型、操作、应用及其优缺点。
平凡之路.
2024/10/09
4800
数据结构--堆的深度解析
数据结构——二叉堆
首先需要了解三个函数。这三个函数可以通过索引检索出父节点,也可以通过父节点的索引检索出子节点。例如下面一个最小二叉堆,可用数组的表示:
多云转晴
2020/03/28
4840
【数据结构】堆的概念、结构、模拟实现以及应用
2)堆又分为大堆和小堆,大堆就是树里面任何一个父节点都大于子节点,所以根节点是最大值;小堆就是树里面任何一个父节点都小于子节点,所以根节点也是最小值。
羚羊角
2024/12/29
5430
【数据结构】堆的概念、结构、模拟实现以及应用
动图解析面试常见排序算法(下)
归并排序是分治算法的典型应用.所谓归并即是将两个有序的数组归并成一个更大的有序数组.
周三不加班
2019/06/04
4300
动图解析面试常见排序算法(下)
推荐阅读
相关推荐
Java数据结构与算法解析(十三)——优先级队列
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档