一、堆和二叉堆

堆,英文名称Heap,所谓二叉堆(也有直接称二叉堆为堆的),本质上是一个完全二叉树,前面也提到过,如果树接近于完全二叉树或者满二叉树,采用顺序存储代价会小一点,因此常见的二叉堆均是顺序实现的。

按照排列的顺序可以分为最大堆和最小堆,最大堆的特征是父节点一定大于(依据情况判断是大于等于还是严格大于,数据结构归根到底还是用来使用的)子节点的数据。同样,有最大堆就会有最小堆,最小堆的 父节点数据小于其子节点的数据,因此根节点的数据是最小的。下面左图是一个最小堆,右图是一个最大堆。

    

二、二叉堆的插入和删除

详细来看,二叉堆的主要操作就是插入和删除。以一个最小堆为例,我们详细介绍插入和删除的操作。

    

以上是一个最小二叉堆的插入过程,比如我们要插入一个节点0,但是他的数据小于它父节点的数据,因此它和它父节点交换数据,如上面的第三张图所示。然后继续判断,它仍连续两次小于父节点数据,因此再交换两次数据,形成最终的那张图,就是插入后的最小二叉堆。

     

一般来说,二叉堆的删除主要是指删除堆顶的数据,即根节点的数据。我们使用之前插入后得到的二叉堆作为目标,我们对其进行删除操作,假设再次删除节点0,然后将数组中最后一位(节点3)填充进去;然后和子节点的数据进行比较,这时候我们必须要从左右子节点中选出更小的那一个作比较,显然是左节点1较小;如果该节点数据大于子节点(较小的那个)的数据,那就和子节点数据进行交换,直至符合条件;

而查找性的删除则比较复杂,从堆尾补充进删除位置的新数据首先要和父节点的数据进行比较,如果小于,就把该节点一直往上交换,直至停止。但本实例中该节点是根节点,不存在父节点,因此就没有这一步;然后按照上面那一段描述与子节点进行比较,交换。

三、二叉堆的Java实现

成员域由ArrayList<Y> data代表堆中的数据,因为数组无法适配泛型。

插入

  1. public void insert(Y y)
  2. {
  3. data.add(y);
  4. int index = data.size() - 1;
  5. while(((index + 1) / 2 - 1) >= 0 && data.get(index).compareTo(data.get((index + 1) / 2 - 1)) < 0)
  6. {
  7. Y temp = data.get((index + 1) / 2 - 1);
  8. data.set((index + 1) / 2 - 1, y);
  9. data.set(index,temp);
  10. index = (index + 1) / 2 - 1;
  11. }
  12. }

删除

  1. public boolean delete(Y y)
  2. {
  3. if(data.size() == 0)
  4. return false;
  5. else if (data.indexOf(y) == -1)
  6. return false;
  7. else
  8. {
  9. int index = data.indexOf(y);
  10. data.set(index, data.get(data.size() - 1));
  11. data.remove(data.size() - 1);

  12. /* parent */
  13. while(((index + 1) / 2 - 1) >= 0 && data.get(index).compareTo(data.get((index + 1) / 2 - 1)) < 0)
  14. {
  15. Y temp = data.get((index + 1) / 2 - 1);
  16. data.set((index + 1) / 2 - 1, data.get(index));
  17. data.set(index,temp);
  18. index = (index + 1) / 2 - 1;
  19. }
  20.  
  21. /* child */
  22.  
  23. while((2 * index + 1) <= data.size()-1)
  24. {
  25. if ((2 * index + 2) <= data.size()-1) //如果该节点左右子树均存在
  26. {
  27. int cmp = data.get(2 * index + 1).compareTo(data.get(2 * index + 2)); //比较子树的大小
  28. if (cmp > 0) //左子树大于右子树,则交换右子树
  29. {
  30. if (data.get(index * 2 + 2) .compareTo(data.get(index)) < 0 ) {
  31. Y temp = data.get(index * 2 + 2);
  32. data.set(index * 2 + 2, data.get(index));
  33. data.set(index, temp);
  34. index = index * 2 + 2;
  35. }
    else
    break;
  36. }
  37.  
  38. else //右子树大于左子树,则交换左子树
  39. {
  40. if(data.get(index * 2 + 1) .compareTo(data.get(index)) < 0 ) {
  41. Y temp = data.get(index * 2 + 1);
  42. data.set(index * 2 + 1, data.get(index));
  43. data.set(index, temp);
  44. index = index * 2 + 1;
  45. }
    else
    break;
  46. }
  47. }
  48.  
  49. else if ((2 * index + 2) > data.size()-1) //只存在左子树
  50. {
  51. if(data.get(index * 2 + 1) .compareTo(data.get(index)) < 0 ) { //判断左子树和节点大小
  52. Y temp = data.get(index * 2 + 1);
  53. data.set(index * 2 + 1, data.get(index));
  54. data.set(index, temp);
  55. index = index * 2 + 1;
  56. }
    else
    break;
  57. }
  58. }
  59. return true;
  60. }
  61. }

测试代码1

以此堆为例,插入0后删除0

  1. Heap <Integer> h = new Heap<>();
  2. Integer [] i = {1,2,5,3,4,6,7};
  3. for (int j = 0; j < i.length; j++)
  4. {
  5. h.insert(i[j]);
  6. }
  7.  
  8. h.traverse();
  9. System.out.println();
  10.  
  11. h.insert(0);
  12.  
  13. h.traverse();
  14. System.out.println();
  15.  
  16. h.delete(0);
  17.  
  18. h.traverse();

Test 1

结果1:

————————————————————————————————————————————————————————

测试代码2

  1. Heap <Integer> h = new Heap<>();
  2. Integer [] i = {10,20,40,30,60,80,110,50,70,90,100};
  3. for (int j = 0; j < i.length; j++)
  4. {
  5. h.insert(i[j]);
  6. }
  7.  
  8. h.traverse();
  9. System.out.println();
  10.  
  11. h.insert(0);
  12.  
  13. h.traverse();
  14. System.out.println();
  15.  
  16. h.delete(0);
  17.  
  18. h.traverse();

Test 2

结果2:

二叉堆的介绍和Java实现的更多相关文章

  1. 二叉堆的构建(Java)

    package com.rao.linkList; /** * @author Srao * @className BinaryHeap * @date 2019/12/3 14:14 * @pack ...

  2. 关于博主skywang123456文章——二叉堆(三)之 Java的实现的质疑

    博客园博主skywang123456(以下简称s博主)是一个大牛级的人物,相信很多程序员都拜读过他的博客,我也不例外,并且受益匪浅.但是对于文章二叉堆(三)之 Java的实现我有一些疑惑,写在这里,供 ...

  3. 二叉堆的应用——查找长度为N数组中第M大数

    看到这个题目首先想到是排序,那么时间复杂度自然就是O(NlgN).那么使用二叉堆如何解决呢? 对于下面一个数组,共有12个元素,我们的目标就是找出第5大元素——12 首先建立一个具有M个元素的最小堆, ...

  4. 二叉堆(三)之 Java的实现

    概要 前面分别通过C和C++实现了二叉堆,本章给出二叉堆的Java版本.还是那句话,它们的原理一样,择其一了解即可. 目录1. 二叉堆的介绍2. 二叉堆的图文解析3. 二叉堆的Java实现(完整源码) ...

  5. 二叉堆(一)之 图文解析 和 C语言的实现

    概要 本章介绍二叉堆,二叉堆就是通常我们所说的数据结构中"堆"中的一种.和以往一样,本文会先对二叉堆的理论知识进行简单介绍,然后给出C语言的实现.后续再分别给出C++和Java版本 ...

  6. 二叉堆(二)之 C++的实现

    概要 上一章介绍了堆和二叉堆的基本概念,并通过C语言实现了二叉堆.本章是二叉堆的C++实现. 目录1. 二叉堆的介绍2. 二叉堆的图文解析3. 二叉堆的C++实现(完整源码)4. 二叉堆的C++测试程 ...

  7. 二叉堆的实现(数组)——c++

    二叉堆的介绍 二叉堆是完全二元树或者是近似完全二元树,按照数据的排列方式可以分为两种:最大堆和最小堆.最大堆:父结点的键值总是大于或等于任何一个子节点的键值:最小堆:父结点的键值总是小于或等于任何一个 ...

  8. 数据结构与算法——优先队列类的C++实现(二叉堆)

    优先队列简单介绍: 操作系统表明上看着是支持多个应用程序同一时候执行.其实是每一个时刻仅仅能有一个进程执行,操作系统会调度不同的进程去执行. 每一个进程都仅仅能执行一个固定的时间,当超过了该时间.操作 ...

  9. 纯数据结构Java实现(6/11)(二叉堆&优先队列)

    堆其实也是树结构(或者说基于树结构),一般可以用堆实现优先队列. 二叉堆 堆可以用于实现其他高层数据结构,比如优先队列 而要实现一个堆,可以借助二叉树,其实现称为: 二叉堆 (使用二叉树表示的堆). ...

随机推荐

  1. 【VS开发】文件共享内存2

    在32位的Windows系统中,每一个进程都有权访问他自己的4GB(232=4294967296)平面地址空间,没有段,没有选择符,没有near和far指针,没有near和far函数调用,也没有内存模 ...

  2. poj1753 (高斯消元法求异或方程组)

    题目链接:http://poj.org/problem?id=1753 题意:经典开关问题,和poj1222一样,进行两次高斯消元即可,只用初始化的时候改一下初始状态.可能存在无解或多解的情况,多解要 ...

  3. poj1556 The Doors(叉积判断线段相交)

    题目链接:https://vjudge.net/problem/POJ-1556 题意:在一个矩形内,起点(0,5)和终点(10,5)是固定的,中间有n个道墙(n<=18),每道墙有两个門,求起 ...

  4. sysbench的简单安装

    1. 下载 可以到网站上面找 我用到的这个是201908最新的 wget https://src.fedoraproject.org/repo/pkgs/sysbench/sysbench-1.0.1 ...

  5. 自动输入密码执行远程服务器上的java -version命令

    自动输入密码执行远程服务器上的java -version命令 for i in $(seq 1 253);do sshpass -p "W123hz" ssh weili@192. ...

  6. SQL SERVER DAY函数

    定义: DAY函数返回指定日期的日的部分 语法: DAY(date) 参数: ①date参数是合法的日期表达式. 返回值: int型数据 例:  声明:本文是本人查阅网上及书籍等各种资料,再加上自己的 ...

  7. 题目13 在O(1)时间删除链表节点

    ///////////////////////////////////////////////////////////////////////////////////// // 3. 题目13 在O( ...

  8. k8s-traefik默认80端口

    vim traefik.yaml kind: Deployment apiVersion: extensions/v1beta1 metadata: name: traefik-ingress-con ...

  9. linux mysql 数据库操作导入导出 数据表导出导入

    linux mysql 数据库操作导入导出 数据表导出导入 1,数据库导入 mysql -uroot -p show databases; create database newdb; use 数据库 ...

  10. UPX编译及so加固

    UPX编译及so加固 来源 https://www.cnblogs.com/Reverser/p/5778042.html 参考 http://www.cnblogs.com/fishou/p/420 ...