堆分为大顶堆,和小顶堆。 什么是堆? 堆可以看成是一棵二叉树,二叉树的元素是一个数组不断的从左到右轮训放置。如果是大顶堆,则大的数放上面一层,小的数放下面一层。上一层的数,一定大于下一层的数。小顶堆则相反。

  那么,如何实现一个大顶堆?这里我用一个链表来实现。

实现堆很简单,只要牢记他的原理就行了。

  添加新元素:添加至数组末尾。然后对这个末尾节点不断的向上层冒泡。直到找到一个合适的节点放置。

  删除元素:从数组末尾取出一个元素对当前要删除的元素进行覆盖,后删除末尾的元素。然后从当前节点不断的向下冒泡。就能找到一个合适的位置进行放置。

  上层元素和下层元素之间的关系:上层元素(索引为:index )和下层元素索引存在 2 * index + 1(左孩子节点) 2 * index + 2(右孩子节点)的关系。

实现源码:

  1. package heap;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.Iterator;
  5. import java.util.List;
  6.  
  7. import org.junit.Test;
  8.  
  9. public class Heap {
  10. private List<Integer> heapArray;
  11. public Heap() {
  12. super();
  13. this.heapArray = new ArrayList();
  14. }
  15. //添加元素进堆
  16. public void Push(Integer x) {
  17. heapArray.add(x);
  18. trickleUp(heapArray.size()-1);
  19. }
  20. //删除元素
  21. public void Pop() {
  22. heapArray.set(0, heapArray.get(heapArray.size()-1));
  23. heapArray.remove(heapArray.size()-1);
  24. trickleDown(0);
  25. }
  26. //取出根数据
  27. public Integer Top() {
  28. return heapArray.get(0);
  29. }
  30. //判断是否为空
  31. public boolean isEmpty() {
  32. if(Top() == null) {
  33. return true;
  34. }
  35. return false;
  36. }
  37. //向上渗透
  38. public void trickleUp(int index) {
  39. int parent = (index-1) / 2;
  40. Integer bottom = heapArray.get(index);
  41. while(index > 0 && heapArray.get(parent) < bottom) {
  42. heapArray.set(index, heapArray.get(parent));
  43. index = parent;
  44. parent = (parent - 1) / 2;
  45. }
  46. heapArray.set(index, bottom);
  47. }
  48. //向下渗透
  49. public void trickleDown(int index) {
  50. Integer top = heapArray.get(0);
  51. int lagerChild;
  52. while(index < heapArray.size()/2) {
  53. int leftChild = index * 2 + 1;
  54. int rightChild = index * 2 + 2;
  55. if(rightChild < heapArray.size() && heapArray.get(leftChild) < heapArray.get(rightChild)) {
  56. lagerChild = rightChild;
  57. }else {
  58. lagerChild = leftChild;
  59. }
  60. if(top >= heapArray.get(lagerChild)) {
  61. break;
  62. }
  63. heapArray.set(index, heapArray.get(lagerChild));
  64. index = lagerChild;
  65. }
  66. heapArray.set(index, top);
  67. }
  68. }

测试程序:

  1. @Test
  2. public void fun() {
  3. Heap p = new Heap();
  4. p.Push(20);
  5. p.Push(30);
  6. p.Push(15);
  7. System.out.println(p.Top());
  8. p.Push(90);
  9. p.Push(35);
  10. System.out.println(p.Top());
  11. p.Pop();
  12. System.out.println(p.Top());
  13. }

测试结果:

  1. 30
  2. 90
  3. 35

 堆排序:

堆排序非常简单,利用大顶堆的顶一定是堆元素里面的最大值。那么我们就可以将一系列数据存进去,再不断的取出顶元素。取除的元素就是一个排好序的元素。

源码:

  

  1. public static void main(String[] args) {
  2. Heap h = new Heap();
  3. h.Push(2);
  4. h.Push(1);
  5. h.Push(4);
  6. h.Push(6);
  7. System.out.println(h.Top());
  8. h.Pop();
  9. System.out.println(h.Top());
  10. h.Pop();
  11. System.out.println(h.Top());
  12. h.Pop();
  13. System.out.println(h.Top());
  14. }

结果:

  1. 6
  2. 4
  3. 2
  4. 1

至此,堆排序就已经做好了。

数据结构Java版之堆&堆排序(九)的更多相关文章

  1. 数据结构Java版之交换算法(一)

    交换的本质是拷贝,其中拷贝包括两种方式.值拷贝和指针拷贝,在java中没有指针,为此,我们可以理解为地址拷贝,在我看来,指针就是地址. 1.传值方式示例: 由上述示例可得,传值,不能起到交换的作用,原 ...

  2. 数据结构Java版之广度优先图(十三)

    广度优先,则是用的队列,将每一层的节点先存入队列中去,后依次取出队列中的节点,显示与当前节点存在边,但是未被访问过的节点,也就是下一层与之相联系的节点,再将这些节点存入队列.经过层层迭代,就可以完全遍 ...

  3. 数据结构Java版之深度优先-图(十二)

    这里用深度优先遍历存在矩阵里面的图. 深度优先利用的是栈的FIFO特性.为此遍历到底后,可以找到最相邻的节点继续遍历.实现深度优先,还需要在节点加上一个访问标识,来确定该节点是否已经被访问过了. 源码 ...

  4. 数据结构Java版之邻接矩阵实现图(十一)

    邻接矩阵实现图,是用一个矩阵,把矩阵下标作为一个顶点,如果顶点与顶点之间有边.那么在矩阵对应的点上把值设为 1 .(默认是0) package mygraph; import java.util.Li ...

  5. 数据结构Java版之邻接表实现图(十)

    邻接表实现图,实际上是在一个数组里面存放链表,链表存放的是连接当前节点的其他节点. package mygraph; import java.util.ArrayList; import java.u ...

  6. 数据结构Java版之遍历二叉树(六)

    二叉树是我们在程序中用的最多的一种树(个人观点).最简单的一个二叉树是由一个根节点,两个子节点(一左一右成左右孩子节点)组成.二叉树是数组和链表的结合,即包含了数组的快速查找优点,又包含了链表的快速添 ...

  7. 数据结构Java版之递归与迭代算法(五)

    递归的概念很简单,就是自己调用自己. 而迭代,则是通过修改初始化数据,得到中间结果,然后不断的对中间结果进行修改,而得到最终结果.简单来说迭代就是循环. 在此,我们用一个比较经典的Fibonacci数 ...

  8. 数据结构Java版之基数排序(四)

    基数排序: 基数排序分为两种:第一种是LSD ,从最低位开始排序, 第二种是 MSD 从最高位开始排.这里介绍第一种LSD排序算法. 首先,我们先了解什么是基数.基数是根据具体的排序情况而定的,比如我 ...

  9. 数据结构Java版之红黑树(八)

    红黑树是一种自动平衡的二叉查找树,因为存在红黑规则,所以有效的防止了二叉树退化成了链表,且查找和删除的速度都很快,时间复杂度为log(n). 什么是红黑规则? 1.根节点必须是黑色的. 2.节点颜色要 ...

随机推荐

  1. apk反编译工具包for Mac OS的使用

    在本文中我将介绍如何在Mac OS X上使用apktool.jar.dex2jar.jd-gui来进行apk的反编译和查看源码.下面会提供每个工具的下载地址. 测试环境:OS X EI Capitan ...

  2. SQL统计部门人数,人数为0的部门也要显示出来

    相同点:它们都以一张部门表(或类别表),其它表都有部门编号DepartmentID(类别编号) 案例一:一张表 select c.DepartmentID,c.DepartmentName, t.Nu ...

  3. Android笔记(七十二) Style和Theme

    我们尝尝需要使用setText.setColor.setTextSize等属性来设置控件的样式,但是每个控件都需要设置这些属性,工作量无疑是巨大的,并且后期维护起来也不方便. Style Androi ...

  4. 【转】DATA_SECTION 和CODE_SECTION 的区别

    请问#pragma DATA_ALIGN有什么作用? 下面是我在EDMA的一个例程中摘录的几句话:#pragma DATA_ALIGN(ping,128);#pragma DATA_ALIGN(pon ...

  5. gitlab及jenkins

    1.安装配置gitlab服务,在gitlab新建一个仓库,配置本地密钥,并通过ssh方式拉取gitlab仓库代码 https://packages.gitlab.com/gitlab/gitlab-c ...

  6. 手写一个简易版Tomcat

    前言 Tomcat Write MyTomcat Tomcat是非常流行的Web Server,它还是一个满足Servlet规范的容器.那么想一想,Tomcat和我们的Web应用是什么关系? 从感性上 ...

  7. 《hello-world》第九次团队作业:【Beta】Scrum meeting 2

    项目 内容 这个作业属于哪个课程 2016级计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 实验十三 团队作业9:Beta冲刺与团队项目验收 团队名称 <hello--wor ...

  8. python_并发编程——多进程的第二种启动方式

    1.多进程的第二种启动方式 import os from multiprocessing import Process # 创建一个自定义类,继承Process类 class MyProcess(Pr ...

  9. web项目转为maven项目

    声明一下项目本来就是maven项目,只是刚开始部署的时候转为maven项目!!! 2.查看POM文件 3.导入依赖jar包(编译,运行,打包) 4. 注意项目为Maven+java 加载jar包小技巧

  10. lstm-bp过程的手工源码实现

    近些年来,随着深度学习的崛起,RNN模型也变得非常热门.如果把RNN模型按照时间轴展开,它也类似其它的深度神经网络模型结构.因此,我们可以参照已有的方法训练RNN模型. 现在最流行的一种RNN模型是L ...