优先队列priority queue是同意至少下列两种操作的数据结构:insert插入以及deleteMin(删除最小者),它的工作是找出,返回并删除优先队列中最小的元素。insert操作等价于enqueue入队。而deleteMin则是dequeue出队在优先队列中的等价操作。

一种实现优先队列的方法是使用二叉堆binary heap,它的使用对于优先队列的实现相当普遍,以至于当堆heap这个词不加修饰地用在优先队列的上下文中时,一般都是指数据结构的这样的实现。在本节。我们把二叉堆仅仅叫做堆。像二叉查找树一样,堆也有两个性质,即结构性和堆序性。恰似AVL树,对堆的一次操作可能破坏这两个性质中的一个。因此,堆得操作必须到堆得全部性质都被满足时才干终止。其实这并不难做到。

堆是一棵被全然填满的二叉树,有可能的例外是在底层。底层上的元素从左到右填入。这种树称为全然二叉树。easy证明。一棵高为h的全然二叉树有2^h到2^(h+1)-1个节点。

这意味着全然二叉树的高是logN向下取整,显然它是O(logN)。

一个重要的观察发现,由于全然二叉树这么有规律,所以它能够用一个数组表示而不须要使用链。对于数组中任一位置i上的元素。其左儿子在位置2i上,右儿子在左儿子后的单元(2i+1)中,它的父亲则在位置i/2中。因此,这里不仅不须要链。并且遍历该树所须要的操作极简单。在大部分计算机上执行非常可能非常快。这样的实现的唯一问题在于,最大的堆大小须要事先预计。但一般这并不成问题。

下面是一个二叉堆的实现:

import java.util.NoSuchElementException;
import java.util.Random; public class BinaryHeap<AnyType extends Comparable<? super AnyType>> {
private static final int DEFAULT_CAPACITY = 10;// 默认容量
private int currentSize; // 当前堆大小
private AnyType[] array; // 数组 public BinaryHeap() {
this(DEFAULT_CAPACITY);
} @SuppressWarnings("unchecked")
public BinaryHeap(int capacity) {
currentSize = 0;
array = (AnyType[]) new Comparable[capacity + 1];
} @SuppressWarnings("unchecked")
public BinaryHeap(AnyType[] items) {
currentSize = items.length;
array = (AnyType[]) new Comparable[(currentSize + 2) * 11 / 10];
int i = 1;
for (AnyType item : items) {
array[i++] = item;
}
buildHeap();
} /**
* 从随意排列的项目中建立堆,线性时间执行
*/
private void buildHeap() {
for (int i = currentSize / 2; i > 0; i--) {
percolateDown(i);
}
} /**
* 堆内元素向下移动
*
* @param hole
* 下移的開始下标
*/
private void percolateDown(int hole) {
int child;
AnyType tmp = array[hole];
for (; hole * 2 <= currentSize; hole = child) {
child = hole * 2;
if (child != currentSize
&& array[child + 1].compareTo(array[child]) < 0) {
child++;
}
if (array[child].compareTo(tmp) < 0) {
array[hole] = array[child];
} else {
break;
}
}
array[hole] = tmp;
} /**
* 插入一个元素
*
* @param x
* 插入元素
*/
public void insert(AnyType x) {
if (isFull()) {
enlargeArray(array.length * 2 + 1);
}
int hole = ++currentSize;
for (; hole > 1 && x.compareTo(array[hole / 2]) < 0; hole /= 2) {
array[hole] = array[hole / 2];
}
array[hole] = x;
} /**
* 堆是否满
*
* @return 是否堆满
*/
public boolean isFull() {
return currentSize == array.length - 1;
} /**
* 堆是否空
*
* @return 是否堆空
*/
public boolean isEmpty() {
return currentSize == 0;
} /**
* 清空堆
*/
@SuppressWarnings("unused")
public void makeEmpay() {
currentSize = 0;
for (AnyType anyType : array) {
anyType=null;
}
} /**
* 找到堆中最小元素
* @return 最小元素
*/
public AnyType findMin() {
if (isEmpty())
return null;
return array[1];
} /**
* 删除堆中最小元素
* @return 删除元素
*/
public AnyType deleteMin() {
if (isEmpty()) {
throw new NoSuchElementException();
}
AnyType minItem = findMin();
array[1] = array[currentSize];
array[currentSize--] = null;
percolateDown(1);
return minItem;
} /**
* 扩大数组容量
* @param newSize 新的容量
*/
@SuppressWarnings("unchecked")
private void enlargeArray(int newSize) {
AnyType[] old = array;
array = (AnyType[]) new Comparable[newSize];
for (int i = 0; i < old.length; i++) {
array[i] = old[i];
}
} /**
* 输出数组中的元素
*/
public void printHeap() {
for (AnyType anyType : array) {
System.out.print(anyType + " ");
}
} public static void main(String[] args) {
BinaryHeap<Integer> heap = new BinaryHeap<Integer>();
for (int i = 0; i < 20; i++) {
heap.insert(i);
}
heap.deleteMin();
heap.deleteMin();
heap.deleteMin();
heap.printHeap();
}
}

运行结果:

null 3 4 5 7 9 11 6 15 8 17 10 18 12 13 14 19 16 null null null null null

数据结构(Java语言)——BinaryHeap简单实现的更多相关文章

  1. Java语言实现简单FTP软件------>FTP软件主界面的实现(四)

    首先看一下该软件的整体代码框架                        1.首先介绍程序的主入口FTPMain.java,采用了一个漂亮的外观风格 package com.oyp.ftp; im ...

  2. Java语言实现简单FTP软件------>源码放送(十三)

    Java语言实现简单FTP软件------>FTP协议分析(一) Java语言实现简单FTP软件------>FTP软件效果图预览之下载功能(二) Java语言实现简单FTP软件----- ...

  3. Java语言实现简单FTP软件------>上传下载管理模块的实现(十一)

    1.上传本地文件或文件夹到远程FTP服务器端的功能. 当用户在本地文件列表中选择想要上传的文件后,点击上传按钮,将本机上指定的文件上传到FTP服务器当前展现的目录,下图为上传子模块流程图 选择好要上传 ...

  4. 数据结构--Java语言描述

    本篇文章是为了记录自己在学习数据结构时的笔记,会对常见的数据结构做基本的介绍以及使用Java语言进行实现.包括 动态数组 栈 队列 链表 二分搜索树 优先队列和堆 线段树 Trie树 并查集 AVL树 ...

  5. 数据结构(Java语言描述)-第一章:概述

    第一章 概述 1.0 序言 自己为啥要学数据结构嘞,我觉得主要有以下三个原因: 前段时间在看并发编程时,发现aqs,corrunthashmap等底层都用到了数据结构,主要的有队列,还有链表,学习数据 ...

  6. 用Java语言实现简单的词法分析器

    编译原理中的词法分析算是很重要的一个部分,原理比较简单,不过网上大部分都是用C语言或者C++来编写,笔者近期在学习Java,故用Java语言实现了简单的词法分析器. 要分析的代码段如下: 输出结果如下 ...

  7. Java语言的简单基础

    1.Java 是一种高级程序设计语言. 2.Java 是大小敏感的程序语言. 3.Java 中的 public 修饰的类名一般要与文件名相同,但也有特列:内部类. 4.Java 程序能在任何操作系统中 ...

  8. 设计模式(Java语言)- 简单工厂模式

    简单工厂模式有称为静态工厂模式,属于设计模式中的创建型模式.简单工厂模式通过对外提供一个静态方法来统一为类创建实例.简单工厂模式的目的是实现类与类之间解耦,其次是客户端不需要知道这个对象是如何被穿创建 ...

  9. java语言实现简单接口工具--粗简版

    2016注定是变化的一年,忙碌.网红.项目融资失败,现在有点时间整整帖子~~ 目标: 提高工作效率与质量,能支持平台全量接口回归测试与迭代测试也要满足单一接口联调测试. 使用人员: 测试,开发 工具包 ...

  10. Java语言实现简单FTP软件------>FTP软件本地窗口的实现(五)

    1.首先看一下本地窗口的布局效果 2.看一下本地窗口实现的代码框架 2.本地窗口的具体实现代码LocalPanel.java package com.oyp.ftp.panel.local; impo ...

随机推荐

  1. 浅谈redux 中间件的原理

    在使用redux管理异步数据流的时候,我们会使用中间件,以redux-thunk中间件为例,我们做一下分析: 首先是构建store,我们需要以下代码进行揉入中间件的类似creatStore函数的构造: ...

  2. C# 后台首次加载时才执行

    protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { } } 写在 if (!IsPostBack) { ...

  3. maven的项目管理方面细节

    1.1    Maven 1.依赖管理.jar包.工程之间的依赖. 2.项目构建.实现项目的一步构建. 3.工程聚合.工程继承.工程依赖. 1.2    Maven的工程类型: 1.war包工程 2. ...

  4. KVM(二)CPU 和内存虚拟化

    1. 为什么需要 CPU 虚拟化 X86 操作系统是设计在直接运行在裸硬件设备上的,因此它们自动认为它们完全占有计算机硬件.x86 架构提供四个特权级别给操作系统和应用程序来访问硬件. Ring 是指 ...

  5. Python垃圾回收机制:gc模块(zz)

    在Python中,为了解决内存泄露问题,采用了对象引用计数,并基于引用计数实现自动垃圾回收. 由于Python 有了自动垃圾回收功能,就造成了不少初学者误认为不必再受内存泄漏的骚扰了.但如果仔细查看一 ...

  6. 天猫首页迷思之-jquery实现整个div的懒加载(2)-插件面向对象化-闭包和原型的实例

    前文有简单的实现了一个制作懒加载的方法,但其实以方法的形式做插件扩展性不强.那么本文就来用面向对象的方法将其制作成一个真正的插件: 我想要的最终的调用效果是: $(".loading&quo ...

  7. [BZOJ4006][JLOI2015]管道连接 状压dp+斯坦纳树

    4006: [JLOI2015]管道连接 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1020  Solved: 552[Submit][Statu ...

  8. foreach 与 Linq的 Select 效率问题

    Resharper 是一个非常强大的C#编程辅助工具,有着非常强的提示功能,代码纠正,代码简化等等 在编码过程中注意到这么一件事,可能是大家经常会遇到的: 遍历某个集合,然后经过处理生成另外一个集合, ...

  9. CSS3实现鼠标经过图片时图片放大

    在鼠标经过图片时,图片被放大,而且还有个过渡的效果.... <!DOCTYPE html> <html> <head> <link href="cs ...

  10. HDU 6354.Everything Has Changed-简单的计算几何、相交相切圆弧的周长 (2018 Multi-University Training Contest 5 1005)

    6354.Everything Has Changed 就是计算圆弧的周长,总周长=大圆周长+相交(相切)部分的小圆的弧长-覆盖掉的大圆的弧长. 相交部分小圆的弧长直接求出来对应的角就可以,余弦公式, ...