Java语言实现二叉堆的打印代码分享

二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树)。二叉堆有两种:最大堆和最小堆。最大堆:父结点的键值总是大于或等于任何一个子节点的键值;最小堆:父结点的键值总是小于或等于任何一个子节点的键值。

打印二叉堆:利用层级关系

我这里是先将堆排序,然后在sort里执行了打印堆的方法printAsTree()

public class MaxHeap<T extends Comparable<? super T>> {
  private T[] data;
  private int size;
  private int capacity;

  public MaxHeap(int capacity) {
    this.capacity = capacity;
    this.size = 0;
    this.data = (T[]) new Comparable[capacity + 1];
  }

  public MaxHeap(T[] arr) {//heapify,数组建堆
    capacity = arr.length;
    data = (T[]) new Comparable[capacity + 1];
    System.arraycopy(arr, 0, data, 1, arr.length);
    size = arr.length;
    for (int i = size / 2; i >= 1; i--) {
      shiftDown(i);
    }
  }

  public int size() {
    return this.size;
  }

  public int getCapacity() {
    return this.capacity;
  }

  public boolean isEmpty() {
    return size == 0;
  }

  public T seekMax() {
    return data[1];
  }

  public void swap(int i, int j) {
    if (i != j) {
      T temp = data[i];
      data[i] = data[j];
      data[j] = temp;
    }
  }

  public void insert(T item) {
    size++;
    data[size] = item;
    shiftUp(size);
  }

  public T popMax() {
    swap(1, size--);
    shiftDown(1);
    return data[size + 1];
  }

  public void shiftUp(int child) {
    while (child > 1 && data[child].compareTo(data[child / 2]) > 0) {
      swap(child, child / 2);
      child /= 2;
    }
  }

  /**
   * @param a data数组中某个元素的下角标
   * @param b data数组中某个元素的下角标
   * @return 哪个元素大就返回哪个的下角标
   */
  private int max(int a, int b) {
    if (data[a].compareTo(data[b]) < 0) {//如果data[b]大
      return b;//返回b
    } else {//如果data[a]大
      return a;//返回a
    }
  }

  /**
   * @param a data数组中某个元素的下角标
   * @param b data数组中某个元素的下角标
   * @param c data数组中某个元素的下角标
   * @return 哪个元素大就返回哪个的下角标
   */
  private int max(int a, int b, int c) {
    int biggest = max(a, b);
    biggest = max(biggest, c);
    return biggest;
  }

  public void shiftDown(int father) {
    while (true) {
      int lchild = father * 2;
      int rchild = father * 2 + 1;
      int newFather = father;//这里赋不赋值无所谓,如果把下面这个return改成break,那就必须赋值了

      if (lchild > size) {//如果没有左、右孩子
        return;
      } else if (rchild > size) {//如果没有右孩子
        newFather = max(father, lchild);
      } else {//如果有左、右孩子
        newFather = max(father, lchild, rchild);
      }

      if (newFather == father) {//如果原父结点就是三者最大,则不用继续整理堆了
        return;
      } else {//父节点不是最大,则把大的孩子交换上来,然后继续往下堆调整,直到满足大根堆为止
        swap(newFather, father);
        father = newFather;//相当于继续shiftDown(newFather)。假如newFather原来是father的左孩子,那就相当于shiftDown(2*father)
      }
    }
  }

  public static <T extends Comparable<? super T>> void sort(T[] arr) {
    int len = arr.length;
    MaxHeap<T> maxHeap = new MaxHeap<>(arr);
    maxHeap.printAsTree();
    for (int i = len - 1; i >= 0; i--) {
      arr[i] = maxHeap.popMax();
    }
  }

  public static void printArr(Object[] arr) {
    for (Object o : arr) {
      System.out.print(o);
      System.out.print("\t");
    }
    System.out.println();
  }

  public void printSpace(int n) {//打印n个空格(在这里用‘\t'来代替)
    for (int i = 0; i < n; i++) {
      System.out.printf("%3s", "");
    }
  }

  public void printAsTree() {
    int lineNum = 1;//首先遍历第一行
    int lines = (int) (Math.log(size) / Math.log(2)) + 1;//lines是堆的层数
    int spaceNum = (int) (Math.pow(2, lines) - 1);
    for (int i = 1; i <= size; ) { //因为在[1...size]左闭右闭区间存数据,data[0]不存数据

      //每层都是打印这个区间[2^(层数-1) ... (2^层数)-1]。如果堆里的数不够(2^层数)-1个,那就打印到size。所以取min((2^层数)-1,size).
      for (int j = (int) Math.pow(2, lineNum - 1); j <= Math.min(size, (int) Math.pow(2, lineNum) - 1); j++) {
        printSpace(spaceNum); //打印spaceNum个空格
        System.out.printf("%3s", data[j]);//打印数据
        System.out.printf("%3s", "");//图片中绿色方框
        printSpace(spaceNum);//打印spaceNum个空格
        i++;//每打印一个元素就 + 1
      }
      lineNum++;
      spaceNum = spaceNum / 2;
      System.out.println();
    }
  }

  public static void main(String args[]) {
    Integer[] arr = {3, 5, 1, 7, 2, 9, 8, 0, 4, 6, 1, 3, 6, 1, 1};
    sort(arr);
  }
}

执行结果:

总结

以上就是本文关于Java语言实现二叉堆的打印代码分享的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

(0)

相关推荐

  • Java 实现二叉搜索树的查找、插入、删除、遍历

    由于最近想要阅读下JDK1.8 中HashMap的具体实现,但是由于HashMap的实现中用到了红黑树,所以我觉得有必要先复习下红黑树的相关知识,所以写下这篇随笔备忘,有不对的地方请指出- 学习红黑树,我觉得有必要从二叉搜索树开始学起,本篇随笔就主要介绍Java实现二叉搜索树的查找.插入.删除.遍历等内容. 二叉搜索树需满足以下四个条件: 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 任意节点的左.右子

  • java 完全二叉树的构建与四种遍历方法示例

    本来就是基础知识,不能丢的太干净,今天竟然花了那么长的时间才写出来,记一下. 有如下的一颗完全二叉树: 先序遍历结果应该为:1  2  4  5  3  6  7 中序遍历结果应该为:4  2  5  1  6  3  7 后序遍历结果应该为:4  5  2  6  7  3  1 层序遍历结果应该为:1  2  3  4  5  6  7 二叉树的先序遍历.中序遍历.后序遍历其实都是一样的,都是执行递归操作. 我这记录一下层次遍历吧:层次遍历需要用到队列,先入队在出队,每次出队的元素检查是其是

  • java编程实现优先队列的二叉堆代码分享

    这里主要介绍的是优先队列的二叉堆Java实现,代码如下: package practice; import edu.princeton.cs.algs4.StdRandom; public class TestMain { public static void main(String[] args) { int[] a = new int[20]; for (int i = 0; i < a.length; i++) { int temp = (int)(StdRandom.random()*1

  • Java完全二叉树的创建与四种遍历方法分析

    本文实例讲述了Java完全二叉树的创建与四种遍历方法.分享给大家供大家参考,具体如下: 有如下的一颗完全二叉树: 先序遍历结果应该为:1  2  4  5  3  6  7 中序遍历结果应该为:4  2  5  1  6  3  7 后序遍历结果应该为:4  5  2  6  7  3  1 层序遍历结果应该为:1  2  3  4  5  6  7 二叉树的先序遍历.中序遍历.后序遍历其实都是一样的,都是执行递归操作. 我这记录一下层次遍历吧:层次遍历需要用到队列,先入队在出队,每次出队的元素

  • Java编程求二叉树的镜像两种方法介绍

    给出一棵二叉树,求它的镜像,如下图:右边是二叉树是左边二叉树的镜像. 仔细分析这两棵树的特点,看看能不能总结出求镜像的步骤.这两棵树的根节点相同,但他们的左右两个子节点交换了位置.因此我们不妨先在树中交换根节点的两个子节点,就得到了下面一幅图中的第二颗树 解法1(递归) 思路1:如果当前节点为空,返回,否则交换该节点的左右节点,递归的对其左右节点进行交换处理. /*class TreeNode{ int val; TreeNode left=null; TreeNode right=null;

  • Java语言描述二叉树的深度和宽度

    解释: 二叉树的深度:从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度. 二叉树的宽度:二叉树的每一层中都有一定数量的节点,节点数最多的那一层的节点数叫做二叉树的宽度. 思路:递归实现. 1.每个节点都可以看作根节点 2.根节点(任意一个节点)的深度等于它的左子树或右子树深度最大值+1 3.从根结点开始遍历,若遍历到叶子节点,深度为0 //二叉树的深度 public static int Depth(node root){ if(root == null)

  • java 实现最小二叉树堆排序的实例

    java 实现最小二叉堆排序的实例 写在前面: 一觉醒来,我就突然有灵感了...... 最小二叉堆定义: 二叉堆是完全二元树或者是近似完全二元树,最小二叉堆是父结点的键值总是小于或等于任何一个子节点的键值的堆堆. 存储: 二叉堆一般用数组来表示. 根节点在数组中的位置是0,第n个位置的子节点分别在2n+1和 2n+2: 位置k的叶子的父节点位置为(k-1)/2: 实现: /** * @description 元素添加到末尾,和它的父节点比,如果比它小就交换 * @param array * *

  • Java语言实现二叉堆的打印代码分享

    二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树).二叉堆有两种:最大堆和最小堆.最大堆:父结点的键值总是大于或等于任何一个子节点的键值:最小堆:父结点的键值总是小于或等于任何一个子节点的键值. 打印二叉堆:利用层级关系 我这里是先将堆排序,然后在sort里执行了打印堆的方法printAsTree() public class MaxHeap<T extends Comparable<? super T>> { private T[] data; pr

  • Python实现二叉堆

    优先队列的二叉堆实现 在前面的章节里我们学习了"先进先出"(FIFO)的数据结构:队列(Queue).队列有一种变体叫做"优先队列"(Priority Queue).优先队列的出队(Dequeue)操作和队列一样,都是从队首出队.但在优先队列的内部,元素的次序却是由"优先级"来决定:高优先级的元素排在队首,而低优先级的元素则排在后面.这样,优先队列的入队(Enqueue)操作就比较复杂,需要将元素根据优先级尽量排到队列前面.我们将会发现,对于下一

  • C语言每日练习之二叉堆

    目录 一.堆的概念 1.概述 2.定义 3.性质 4.作用 二.堆的存储结构 1.根结点编号 2.孩子结点编号 3.父结点编号 4.数据域 5.堆的数据结构 三.堆的常用接口 1.元素比较 2.交换元素 3.空判定 4.满判定 5.上浮操作 6.下沉操作 四.堆的创建 1.算法描述 2.动画演示 3.源码详解 五.堆元素的插入 1.算法描述 2.动画演示 3.源码详解 五.堆元素的删除 1.算法描述 2.动画演示 3.源码详解 总结 一.堆的概念 1.概述 堆是计算机科学中一类特殊的数据结构的统

  • Java实现二叉堆、大顶堆和小顶堆

    目录 什么是二叉堆 什么是大顶堆.小顶堆 建堆 程序实现 建立大顶堆 逻辑过程 程序实现 建立小顶堆 逻辑过程 程序实现 从堆顶取数据并重构大小顶堆 什么是二叉堆 二叉堆就是完全二叉树,或者是靠近完全二叉树结构的二叉树.在二叉树建树时采取前序建树就是建立的完全二叉树.也就是二叉堆.所以二叉堆的建堆过程理论上讲和前序建树一样. 什么是大顶堆.小顶堆 二叉堆本质上是一棵近完全的二叉树,那么大顶堆和小顶堆必然也是满足这个结构要求的.在此之上,大顶堆要求对于一个节点来说,它的左右节点都比它小:小顶堆要求

  • Java 数据结构与算法系列精讲之二叉堆

    目录 概述 优先队列 二叉堆 二叉堆实现 获取索引 添加元素 siftUp 完整代码 概述 从今天开始, 小白我将带大家开启 Java 数据结构 & 算法的新篇章. 优先队列 优先队列 (Priority Queue) 和队列一样, 是一种先进先出的数据结构. 优先队列中的每个元素有各自的优先级, 优先级最高的元素最先得到服务. 如图: 二叉堆 二叉堆 (Binary Heap) 是一种特殊的堆, 二叉堆具有堆的性质和二叉树的性质. 二叉堆中的任意一节点的值总是大于等于其孩子节点值. 如图: 二

  • 理解二叉堆数据结构及Swift的堆排序算法实现示例

    二叉堆的性质 1.二叉堆是一颗完全二叉树,最后一层的叶子从左到右排列,其它的每一层都是满的 2.最小堆父结点小于等于其每一个子结点的键值,最大堆则相反 3.每个结点的左子树或者右子树都是一个二叉堆 下面是一个最小堆: 堆的存储 通常堆是通过一维数组来实现的.在起始数组为 0 的情形中: 1.父节点i的左子节点在位置 (2*i+1); 2.父节点i的右子节点在位置 (2*i+2); 3.子节点i的父节点在位置 floor((i-1)/2); 维持堆的性质 我们以最大堆来介绍(后续会分别给出最大堆和

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

    前言 在以往工作或者面试的时候常会碰到一个问题,如何实现海量TopN,就是在一个非常大的结果集里面快速找到最大的前10或前100个数,同时要保证内存和速度的效率,我们可能第一个想法就是利用排序,然后截取前10或前100,而排序对于量不是特别大的时候没有任何问题,但只要量特别大是根本不可能完成这个任务的,比如在一个数组或者文本文件里有几亿个数,这样是根本无法全部读入内存的,所以利用排序解决这个问题并不是最好的,所以我们这里就用php去实现一个小顶堆来解决这个问题. 二叉堆 二叉堆是一种特殊的堆,二

  • python下实现二叉堆以及堆排序的示例

    堆是一种特殊的树形结构, 堆中的数据存储满足一定的堆序.堆排序是一种选择排序, 其算法复杂度, 时间复杂度相对于其他的排序算法都有很大的优势. 堆分为大头堆和小头堆, 正如其名, 大头堆的第一个元素是最大的, 每个有子结点的父结点, 其数据值都比其子结点的值要大.小头堆则相反. 我大概讲解下建一个树形堆的算法过程: 找到N/2 位置的数组数据, 从这个位置开始, 找到该节点的左子结点的索引, 先比较这个结点的下的子结点, 找到最大的那个, 将最大的子结点的索引赋值给左子结点, 然后将最大的子结点

  • Java底层基于二叉搜索树实现集合和映射/集合Set功能详解

    本文实例讲述了Java底层基于二叉搜索树实现集合和映射功能.分享给大家供大家参考,具体如下: 前言:在第5章的系列学习中,已经实现了关于二叉搜索树的相关操作,详情查看第5章即可.在本节中着重学习使用底层是我们已经封装好的二叉搜索树相关操作来实现一个基本的集合(set)这种数据结构. 集合set的特性: 集合Set存储的元素是无序的.不可重复的.为了能达到这种特性就需要寻找可以作为支撑的底层数据结构. 这里选用之前自己实现的二叉搜索树,这是由于该二叉树是不能盛放重复元素的.因此我们可以使用二叉搜索

随机推荐