数据结构_使用二叉堆实现优先队列
来源:互联网 发布:最近破获网络涉枪案件 编辑:程序博客网 时间:2024/05/07 22:46
本文将先简单的介绍一下二叉堆,然后再使用二叉堆实现优先队列。
1、二叉堆实际上就是一种完全二叉树,即除了树的最后一层节点不需要是满的,其他的每一层从左到右都是完全满的。
2、常见的二叉堆有最大堆和最小堆,区别在于根节点是树中的最大值还是最小值。
3、在使用二叉堆实现的优先队列中进行数据的插入、删除的时间复杂度为O(logN)。
4、堆是弱序的,或者说堆是基本无序的。因为不像二叉搜索树一样中节点的右子节点都大于左子结点,在堆中只需要满足从根节点到任意个页节点的路径是单调递增或单调递减的即可。这意味着,堆不能很快的查找指定关键字对应的元素,同样也不能很快的删除指定关键字对应的元素。但是在堆上可以很快的插入元素,同时还可以很快的删除最大元素(最大堆)/最小元素(最小堆)。
5、数组表示的二叉堆中,节点n的左子结点是节点2n+1,右子结点是节点2n+2,父节点是(n-1)/2。
好了,下面是二叉堆的实现:
package com.wly.algorithmbase.datastructure;/** * 数组实现最大堆、最小堆 * @author wly * */public class BinaryHeap {private final int MAX_HEAP = 1; //最大堆标记private final int MIN_HEAP = 2; //最小堆标记private int type; //用以表示堆的类型private Node[] array; //用于存储树结构的数组private int CAPACITY = 12; //数组扩展步长private int mSize = 0; //用于表示树中当前的元素个数public static void main(String[] args) {//测试最大堆System.out.println("---测试最大堆---");BinaryHeap binaryHeap = new BinaryHeap(1);binaryHeap.insert(new Node("A",23));binaryHeap.insert(new Node("B",26));binaryHeap.insert(new Node("C",43));binaryHeap.insert(new Node("D",12));binaryHeap.insert(new Node("E",78));binaryHeap.insert(new Node("F",66));System.out.println("构建堆:");binaryHeap.printNodes();binaryHeap.remove();System.out.println("\n删除测试");binaryHeap.printNodes();//测试最小堆System.out.println("\n---测试最小堆---");binaryHeap = new BinaryHeap(2);binaryHeap.insert(new Node("A",23));binaryHeap.insert(new Node("B",26));binaryHeap.insert(new Node("C",43));binaryHeap.insert(new Node("D",12));binaryHeap.insert(new Node("E",78));binaryHeap.insert(new Node("F",66));System.out.println("构建堆:");binaryHeap.printNodes();binaryHeap.remove();System.out.println("\n删除测试:");binaryHeap.printNodes();}/** * 构造函数,可以指定最大堆或最小堆 * @param heapType 1表示最大堆,2表示最小堆 */public BinaryHeap(int heapType) {this.type = heapType;array = new Node[CAPACITY];}/** * 插入节点,使用向上筛选法(为什么?保持二叉堆的二叉树的结构) */public void insert(Node node) {if(mSize == 0) { //插入根节点array[mSize++] = node;} else {if(mSize == CAPACITY) {Node[] temp = new Node[array.length + CAPACITY];for(int i = 0;i<array.length;i++) {temp[i] = temp[i];}array = temp;temp = null;}int parentIndex = (mSize-1)/2;int index = mSize;//插入到树最后一层的最右一个array[mSize++] = node;Node parentNode = array[parentIndex];//拿到当前插入节点的父节点switch(type) {case MAX_HEAP://最大堆//向上筛选while(parentNode != null && parentNode.getKey() < node.getKey()) {//交换位置array[parentIndex] = node;array[index] = parentNode;index = parentIndex;parentIndex = (parentIndex-1)/2;parentNode = array[parentIndex]; }break;case MIN_HEAP: //最小堆//向上筛选while(parentNode != null && parentNode.getKey() > node.getKey()) {//交换位置array[parentIndex] = node;array[index] = parentNode;index = parentIndex;parentIndex = (parentIndex-1)/2;parentNode = array[parentIndex]; }break;}}}/** * 移除根节点 * 一、移除根节点 * 二、将二叉堆的最后一层的最右边元素放到根节点位置(保持完全二叉树结构) * 三、将当前根节点向下遍历直到它找到合适的位置 */public Node remove() {Node result;if(mSize == 0) {System.out.println("错误,堆已空无法再行移除元素");return null;} else {//移除根节点,并将最后一个节点放置到根节点位置result = array[0];array[0] = array[mSize-1];array[mSize-1] = null;mSize --;int index = 0;int comparaChildIndex = 0;switch(type) {case MAX_HEAP: //最大堆while(index < mSize/2) { //很神奇的边界条件,可以考虑一下int leftChild = 2*index+1;int rightChild = leftChild+1;//取两个子节点中较大的那个的索引值if(rightChild < mSize && //右子结点是否array[leftChild].getKey() <= array[rightChild].getKey()) {comparaChildIndex = rightChild;} else {comparaChildIndex = leftChild;}if(array[index].getKey() < array[comparaChildIndex].getKey()) {//交换Node temp = array[index];array[index] = array[comparaChildIndex];array[comparaChildIndex] = temp; index = comparaChildIndex;} }break;case MIN_HEAP: //最小堆while(index < mSize/2) { //很神奇的边界条件,可以考虑一下//取两个子节点中较小的那个的索引值if((2*index+2) < mSize&& array[2*index+1].getKey() <= array[2*index+2].getKey()) {comparaChildIndex = 2*index+1;} else {comparaChildIndex = 2*index+2;}if(array[index].getKey() > array[comparaChildIndex].getKey()) {//交换Node temp = array[index];array[index] = array[comparaChildIndex];array[comparaChildIndex] = temp; index = comparaChildIndex;} }break;}return result;}}/** * 打印节点 */public void printNodes() {for(int i=0;i<mSize;i++) {System.out.print(array[i].getKey() + " ");}}}/** * 二叉堆中的节点类 * @author wly * */class Node {String data; //包含的数据int key;public Node(String data, int key) {super();this.data = data;this.key = key;}public String getData() {return data;}public void setData(String data) {this.data = data;}public int getKey() {return key;}public void setKey(int key) {this.key = key;} }运行效果:
---测试最大堆---构建堆:78 43 66 12 23 26 删除测试66 43 26 12 23 ---测试最小堆---构建堆:12 23 43 26 78 66 删除测试:23 26 43 66 78
下面是一个交换的元素移位的技巧,可以使用一次复制和多次覆盖,而不是多次交换。因为交换一次交换需要3次复制!
最后是用上面堆结构实现的优先队列:
package com.wly.algorithmbase.datastructure;/** * 基于二叉堆的优先队列实现 * @author wly * */public class PriorityQueueWithHeap {private BinaryHeap heap;/** * 构造函数 * @param heapType 1最大堆的优先队列,2最小堆的优先队列 */public PriorityQueueWithHeap(int heapType) {heap = new BinaryHeap(heapType);}public void insert(Node node) {heap.insert(node);}public Node remove() {return heap.remove();}}O啦~~~
转载请保留出处:http://blog.csdn.net/u011638883/article/details/17248135
谢谢!!
0 0
- 数据结构_使用二叉堆实现优先队列
- 优先队列_二叉堆
- 数据结构之优先队列--二叉堆(Java实现)
- 数据结构之优先队列--二叉堆(Java实现)
- 优先队列--二叉堆实现
- 优先队列 - 数据结构 (二叉堆)
- 数据结构之优先队列(二叉堆)
- 优先队列(二叉堆实现) + 堆排序
- C#实现优先队列 基于二叉堆 附使用案例
- 优先队列的实现--二叉堆
- 优先队列——二叉堆实现
- 优先队列二叉堆 C语言实现
- 用二叉堆实现优先队列
- 优先队列(利用二叉堆实现)
- 优先队列的数组、二叉堆实现
- 优先队列之二叉堆(JAVA实现)
- 用有序二叉堆实现优先队列
- 优先队列-二叉堆Java实现
- 《解析极限编程:拥抱变化》读后感
- poi写Excel
- GNU开发
- 一个中心,两个基本点,四大作风,八项注意
- Storm rebalance原理及可靠性保证
- 数据结构_使用二叉堆实现优先队列
- python subprocess Popen (转)
- web服务器nginx和apache的对比分析
- javascript 获取项目根路径(备忘)
- 迷雾中的P2P
- 关于double的精度丢失(不是超于最大,最小值)
- Osqledit 工具使用
- 2013年10月《自然》杂志内容精选
- Erlang简单gen_tcp例子