博客园博主skywang123456(以下简称s博主)是一个大牛级的人物,相信很多程序员都拜读过他的博客,我也不例外,并且受益匪浅。但是对于文章二叉堆(三)之 Java的实现我有一些疑惑,写在这里,供有缘人参考。对于而二叉堆的插入,是一个较为简单的方法,这里没有什么问题。但是而二叉堆的删除确是一个稍微复杂一点的操作,事实上,我第一次看这篇博文的时候就感觉有些恍惚不清。一般来说,而二叉堆的删除分为删除堆顶和查找型删除。堆顶删除可以由查找型删除实现,故名思意,直接删除堆顶的数据即可,在二叉堆的实际应用中被广泛使用。而查找型删除首先要查到给定参数的位置,然后删除该元素。而我要指出的问题是博主s使用删除堆顶的代码来代替了查找型删除的代码,而这两个我会举例来说明是不同的。

先来看博主s的删除代码

  1. public int remove(T data) {
  2. // 如果"堆"已空,则返回-1
  3. if(mHeap.isEmpty() == true)
  4. return -1;
  5.  
  6. // 获取data在数组中的索引
  7. int index = mHeap.indexOf(data);
  8. if (index==-1)
  9. return -1;
  10.  
  11. int size = mHeap.size();
  12. mHeap.set(index, mHeap.get(size-1));// 用最后元素填补
  13. mHeap.remove(size - 1); // 删除最后的元素
  14.  
  15. if (mHeap.size() > 1)
  16. filterdown(index, mHeap.size()-1); // 从index号位置开始自上向下调整为最小堆
  17.  
  18. return 0;
  19. }
  1. protected void filterdown(int start, int end) {
  2. int c = start; // 当前(current)节点的位置
  3. int l = 2*c + 1; // 左(left)孩子的位置
  4. T tmp = mHeap.get(c); // 当前(current)节点的大小
  5.  
  6. while(l <= end) {
  7. int cmp = mHeap.get(l).compareTo(mHeap.get(l+1));
  8. // "l"是左孩子,"l+1"是右孩子
  9. if(l < end && cmp<0)
  10. l++; // 左右两孩子中选择较大者,即mHeap[l+1]
  11. cmp = tmp.compareTo(mHeap.get(l));
  12. if(cmp >= 0)
  13. break; //调整结束
  14. else {
  15. mHeap.set(c, mHeap.get(l));
  16. c = l;
  17. l = 2*l + 1;
  18. }
  19. }
  20. mHeap.set(c, tmp);
  21. }

不难理解,将查找到的节点使用堆尾数据填充,之后删除堆尾数据,接着从该节点自上往下调整为最小堆。(目测笔误,应该是最大堆)这是典型的删除堆顶的代码。

博主s在文中给了两个删除的例子。第一个是删除堆顶的元素,因为没有根节点,所以当然适合这个代码。

而第二个例子不是删除根节点的数据,但是为什么也可以?这是一个巧合,恰好是符合某些特定的条件。

如图所示,删除节点60,补充40,40小于其子节点50,然后交换。其实有一种情况,即堆尾数据补充之后会大于原先的父节点,我们来看下图这个堆。

                  

如果我们删除节点2,按照博主s的步骤,将5补充到原有节点2的位置,然后删除原有节点5,这样就变成右图。之后由于没有子节点,因此结束删除操作。可是右边是一个最大堆吗?显然不是!

所以查找型删除应该添加一个步骤,即先判断是否大于父节点(对于最大堆来说),如果大于父节点,则进行向上交换,直到符合最大堆的条件。查找型删除可以参考我这一篇文章二叉堆的介绍和Java实现 。当然我的代码没有过多测试,可能也有没有考虑到的地方,欢迎大家直接勘误。

以上,便是我看完这篇博文的一些质疑和思考,所说的不一定都对。当然,即使博主s真的有失误,也不影响我这么长时间看他博文所获得的进步。

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

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

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

  2. 二项堆(三)之 Java的实现

    概要 前面分别通过C和C++实现了二项堆,本章给出二项堆的Java版本.还是那句老话,三种实现的原理一样,择其一了解即可. 目录1. 二项树的介绍2. 二项堆的介绍3. 二项堆的基本操作4. 二项堆的 ...

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

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

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

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

  5. 【nodejs原理&源码杂记(8)】Timer模块与基于二叉堆的定时器

    目录 一.概述 二. 数据结构 2.1 链表 2.2 二叉堆 三. 从setTimeout理解Timer模块源码 3.1 timers.js中的定义 3.2 Timeout类定义 3.3 active ...

  6. 数据结构图文解析之:二叉堆详解及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  7. 在A*寻路中使用二叉堆

    接上篇:A*寻路初探 GameDev.net 在A*寻路中使用二叉堆 作者:Patrick Lester(2003年4月11日更新) 译者:Panic 2005年3月28日 译者序 这一篇文章,是&q ...

  8. poj 3253 初涉二叉堆 模板题

    这道题很久以前就做过了 当时是百度学习了优先队列 后来发现其实还有个用sort的办法 就是默认sort排序后 a[i]+=a[i-1] 然后sort(a+i,a+i+n) (大概可以这样...答案忘了 ...

  9. PHP利用二叉堆实现TopK-算法的方法详解

    前言 在以往工作或者面试的时候常会碰到一个问题,如何实现海量TopN,就是在一个非常大的结果集里面快速找到最大的前10或前100个数,同时要保证 内存和速度的效率,我们可能第一个想法就是利用排序,然后 ...

随机推荐

  1. 课程设计之C/C++实现用户登录注册

    最近的一个课程设计要求的一个用户登录的程序,通常软件网页等的用户登录注册都是涉及到数据库.但像课程设计这种小程序要求的安全度不高就可以用c/c++实现. 首先,我们要清楚用户登录的流程.应该大家对这些 ...

  2. navicat破解版的下载与激活

    原文链接:http://www.cnblogs.com/djwhome/p/9289295.html 以前一直使用的老版的破解版的navicat,但是最近老是报错 而且连接还特别慢,今天终于不忙了额, ...

  3. 【AtCoder】ARC068

    ARC 068 C - X: Yet Another Die Game 显然最多的就是一次6一次5 最后剩下的可能需要多用一次6或者6和5都用上 #include <bits/stdc++.h& ...

  4. (三)mybatis 的使用(入门)

    目录 mybatis 的使用 -- 准备 mybatis 的使用 -- 搭建好工程结构 mybatis 的使用 -- 创建 sqlMapCnfig.xml 全局配置文件 mybatis 的使用 -- ...

  5. vs code在打开新文件是覆盖上一个窗口的问题

    设置里面有个 enablePreview 去掉就好

  6. PHP无限极菜单

    权限表结构 CREATE TABLE `blog_auth` ( `id` ) unsigned NOT NULL AUTO_INCREMENT COMMENT '序号', `pid` ) NOT N ...

  7. 牛客 P21336 和与或 (数位dp)

    大意: 给定数组$R$, 求有多少个数组$A$, 满足$0\le A_i \le R_i$且$A_0+...+A_{N-1}=A_0\space or ...\space or \space A_{N ...

  8. core路由设置

    全局路由设置 app.UseMvc(routes => { routes.MapRoute( name: "areas", template: "{area:exi ...

  9. 1 简介mvp模式

    1   模型-视图-表示器也称为监视控制器模式 ,如下图表示 2 mvp 模式希望通过表示器(presenter)来关联网页,而不必在他们之间建立严格的 3 一个简单的mvp架构的例子 public ...

  10. LeetCode 滑动窗口题型整理

    一.滑动窗口题型模板 /* * 滑动窗口类型: 模板 */ public List<Integer> slideWindowMode(String s, String t) { // 1 ...