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

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

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

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

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

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

实现源码:

package heap;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import org.junit.Test; public class Heap {
private List<Integer> heapArray;
public Heap() {
super();
this.heapArray = new ArrayList();
}
//添加元素进堆
public void Push(Integer x) {
heapArray.add(x);
trickleUp(heapArray.size()-1);
}
//删除元素
public void Pop() {
heapArray.set(0, heapArray.get(heapArray.size()-1));
heapArray.remove(heapArray.size()-1);
trickleDown(0);
}
//取出根数据
public Integer Top() {
return heapArray.get(0);
}
//判断是否为空
public boolean isEmpty() {
if(Top() == null) {
return true;
}
return false;
}
//向上渗透
public void trickleUp(int index) {
int parent = (index-1) / 2;
Integer bottom = heapArray.get(index);
while(index > 0 && heapArray.get(parent) < bottom) {
heapArray.set(index, heapArray.get(parent));
index = parent;
parent = (parent - 1) / 2;
}
heapArray.set(index, bottom);
}
//向下渗透
public void trickleDown(int index) {
Integer top = heapArray.get(0);
int lagerChild;
while(index < heapArray.size()/2) {
int leftChild = index * 2 + 1;
int rightChild = index * 2 + 2;
if(rightChild < heapArray.size() && heapArray.get(leftChild) < heapArray.get(rightChild)) {
lagerChild = rightChild;
}else {
lagerChild = leftChild;
}
if(top >= heapArray.get(lagerChild)) {
break;
}
heapArray.set(index, heapArray.get(lagerChild));
index = lagerChild;
}
heapArray.set(index, top);
}
}

测试程序:

@Test
public void fun() {
Heap p = new Heap();
p.Push(20);
p.Push(30);
p.Push(15);
System.out.println(p.Top());
p.Push(90);
p.Push(35);
System.out.println(p.Top());
p.Pop();
System.out.println(p.Top());
}

测试结果:

30
90
35

 堆排序:

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

源码:

  

    public static void main(String[] args) {
Heap h = new Heap();
h.Push(2);
h.Push(1);
h.Push(4);
h.Push(6);
System.out.println(h.Top());
h.Pop();
System.out.println(h.Top());
h.Pop();
System.out.println(h.Top());
h.Pop();
System.out.println(h.Top());
}

结果:

6
4
2
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. Java 之 Servlet中的生命周期

    Servlet 生命周期 一.重写servlet方法 当创建一个类,继承 servlet 这个接口时,需要实现里面的抽象方法. import javax.servlet.*; import java. ...

  2. IOS 之 NSBundle 使用

    来源:http://blog.sina.com.cn/s/blog_b0c59541010151rd.html An NSBundle object represents a location in ...

  3. python使用tkinter无法给顶层窗体的输入框设定默认值

    这几天某同学遇到了一个棘手的问题,困扰了很久.今天终于解决了,我来记录一下坑. 情景:python 使用tkinter为第二层窗体(顶层窗体)中的一个输入框设定默认值时,总是无法设置,而且对输入框获取 ...

  4. Kotlin使用处协变的意义与用法

    在上一次https://www.cnblogs.com/webor2006/p/11294849.html中对于Java的协变和Kotlin的协变提到了它们的区别,回忆一下: 其实在Kotlin中也有 ...

  5. LG4720 【模板】扩展卢卡斯定理

    扩展卢卡斯定理 求 \(C_n^m \bmod{p}\),其中 \(C\) 为组合数. \(1≤m≤n≤10^{18},2≤p≤1000000\) ,不保证 \(p\) 是质数. Fading的题解 ...

  6. js判断一个数是不是正整数

    js判断一个数是不是正整数 function isPositiveNum(s){//是否为正整数 var re = /^[0-9]*[1-9][0-9]*$/ ; return re.test(s) ...

  7. onclick与click的区别

    用法: Obj.click(function(){ }); Obj.onclick=function(){ } 相同:效果一样. 区别: 用户或浏览器执行的某种动作,例如click load,mous ...

  8. to_excel

    Signature: df.to_excel( ['excel_writer', "sheet_name='Sheet1'", "na_rep=''", 'fl ...

  9. TVS瞬态抑制二极管选型指南

    一.TVS二极管工作原理 TVS(Transient Voltage Suppressors)二极管,即瞬态电压抑制器,又称雪崩击穿二极管,是采用半导体工艺制成的单个PN结或多个PN结集成的器件.TV ...

  10. Linux 之 光标消失隐藏术

    下面是 Linux 光标突然不见的解决办法: 直接敲命令行就行 echo -e "\033[?25l"  隐藏光标 echo -e "\033[?25h" 显示 ...