数据结构之堆(java)
2015-11-26 11:03
351 查看
记得以前已经实现过堆结构的一些操作,现在看看总有些不和谐,最近在看了看数据结构,觉得还是写的清晰具体一些,也可以方便以后的复习。下面介绍一下堆存在的一些意义。
优先级队列可以用于计算机中的任务调度,在计算机中某些程序和活动需要比其他程序和活动先执行,因此需要给他们分配更高的优先级。
另一个例子是在武器系统中,比如在一个海军巡洋舰系统中。会探测到许多对巡洋舰的威胁,比如来自飞机、导弹、潜水艇的攻击,需要为这些威胁分优先级。例如,离巡洋舰距离近的导弹就比距离远的飞机的优先级更高,这样对应的防范系统(例如地对空导弹)会首先对付它。
堆是一种树,由它实现的优先级队列的插入和删除的时间复杂度是O(logN).尽管这样删除的时间变慢了一点,但插入的时间快的多了。当速度非常重要,且有很多插入操作时,可以选择对来实现优先级队列。
堆可分为大根堆和小根堆,详细的概念就不多说了,为了大家可以真正的了解堆的原理,下面给出详细的代码。
public void setKey(int key){this.iData=key;}}
上面的代码没有堆排序,其实看完上面的代码很容易会想到怎么对一个堆排序,这里就不写出来,留给读者自己完成,以便有一个更清晰的理解。
下面是测试代码:
虽然没有写出堆排序的代码,但还是说一下堆排序的效率吧,尽管它比快速排序略慢,但它比快速排序优越的一点是它对初始数据的分布不敏感。在关键字值按某种排列顺序的情况下,快速排序运行的时间复杂度可以降低到O(N*N)级,然而堆排序对任意排列的数据,其排序的时间复杂度都是O(N*logN)
优先级队列可以用于计算机中的任务调度,在计算机中某些程序和活动需要比其他程序和活动先执行,因此需要给他们分配更高的优先级。
另一个例子是在武器系统中,比如在一个海军巡洋舰系统中。会探测到许多对巡洋舰的威胁,比如来自飞机、导弹、潜水艇的攻击,需要为这些威胁分优先级。例如,离巡洋舰距离近的导弹就比距离远的飞机的优先级更高,这样对应的防范系统(例如地对空导弹)会首先对付它。
堆是一种树,由它实现的优先级队列的插入和删除的时间复杂度是O(logN).尽管这样删除的时间变慢了一点,但插入的时间快的多了。当速度非常重要,且有很多插入操作时,可以选择对来实现优先级队列。
堆可分为大根堆和小根堆,详细的概念就不多说了,为了大家可以真正的了解堆的原理,下面给出详细的代码。
/** * @author Dylan * @date 2015-11-25 * @see 堆的一个节点 * */ public class Node { private int iData; public Node(int key){ this.iData=key; } public int getKey(){ return iData; } <pre name="code" class="java">/** * @author Dylan * @date 2015-11-25 * @see 堆的相关操作 * */ public class Heap { //该数组用于存储堆的节点 private Node[] heapArray; //数据的存储大小 private int maxSize; //当前数组中存储的节点 private int currentSize; /** * 初始化 * */ public Heap(int size){ maxSize=size; heapArray=new Node[maxSize]; currentSize=0; } /** * 判断是否为空 * */ public boolean isEmpty(){ return (currentSize==0); } /** * 插入节点 * */ public boolean insert(int key){ if(currentSize==maxSize) //判断空间是否已满 return false; Node newNode=new Node(key); heapArray[currentSize]=newNode; //将新节点插入最后 trickleUp(currentSize++); //将节点向上调整 return true; } /** * 向上筛选 * */ public void trickleUp(int index){ int parent=(index-1)/2; Node bottom=heapArray[index]; //保存当前节点 while(index>0){ if(heapArray[parent].getKey()>bottom.getKey()) break; else{ heapArray[index]=heapArray[parent]; index=parent; parent=(parent-1)/2; } } heapArray[index]=bottom; } /** * 删除节点 * */ public Node remove(){ if(!isEmpty()){ Node root=heapArray[0]; heapArray[0]=heapArray[--currentSize]; trickleDown(0); return root; } return null; } /** * 向下过滤 * */ public void trickleDown(int index){ int largeChild,leftChild,rightChild; Node top=heapArray[index]; while(index<currentSize/2){ leftChild=2*index+1; rightChild=leftChild+1; if(heapArray[leftChild].getKey()>heapArray[rightChild].getKey()) largeChild=leftChild; else largeChild=rightChild; if(heapArray[largeChild].getKey()>heapArray[index].getKey()) heapArray[index]=heapArray[largeChild]; else break; index=largeChild; } heapArray[index]=top; } /** * 用新数据替换旧的节点 * */ public boolean change(int index,int key){ if(index<0 || index>=currentSize) return false; int oldKey=heapArray[index].getKey(); heapArray[index].setKey(key); if(oldKey>key) trickleDown(index); else trickleUp(index); return true; } /** * 打印堆 * */ public void displayHeap(){ System.out.print("heapArray:"); for(int m=0;m<currentSize;m++){ if(heapArray[m]!=null) System.out.print(heapArray[m].getKey()+" "); } System.out.println(); int column=0; //记录每行节点 int j=0; //记录已打印的节点 int nblank=32; //空格 int itemsPerRow=1; //每行的节点数 String dots="----------------------------------"; System.out.println(dots+dots); while(currentSize>0){ if(column==0) for(int k=0;k<nblank;k++){ System.out.print(" "); } System.out.print(heapArray[j].getKey()); //若所有的节点已打印,则跳出 if(++j==currentSize) break; if(++column == itemsPerRow){ System.out.println(); column=0; itemsPerRow *=2; nblank /=2; }else{ for(int i=0;i<2*nblank-2;i++) System.out.print(" "); } } System.out.println(); System.out.println(dots+dots); } }
public void setKey(int key){this.iData=key;}}
上面的代码没有堆排序,其实看完上面的代码很容易会想到怎么对一个堆排序,这里就不写出来,留给读者自己完成,以便有一个更清晰的理解。
下面是测试代码:
public class HeapTest { /** * 读入字符串 * */ public static String getString(){ InputStreamReader isr=new InputStreamReader(System.in); BufferedReader br=new BufferedReader(isr); String str=""; try { str=br.readLine(); } catch (IOException e) { e.printStackTrace(); } return str; } /** * 取字符串的第一个字符 * */ public static char getChar(){ String s=getString(); return s.charAt(0); } /** * 输入数字 * */ public static int getInteger(){ String s=getString(); return Integer.parseInt(s); } public static void main(String[] args){ int value,value2; Heap theHeap=new Heap(31); boolean success; theHeap.insert(70); theHeap.insert(40); theHeap.insert(50); theHeap.insert(20); theHeap.insert(60); theHeap.insert(100); theHeap.insert(80); theHeap.insert(30); theHeap.insert(10); theHeap.insert(90); theHeap.displayHeap(); while(true){ System.out.print("Enter first letter of : "); System.out.println("show, insert, remove,change"); char choice=getChar(); switch(choice){ case 's': theHeap.displayHeap(); break; case 'i': System.out.print("Enter value to insert:"); value=getInteger(); success=theHeap.insert(value); if(!success) System.out.println("Can't insert !"); break; case 'r': if(!theHeap.isEmpty()) theHeap.remove(); else System.out.println("Can't remove !"); break; case 'c': System.out.print("Enter an index:"); value=getInteger(); System.out.print("Enter new key:"); value2=getInteger(); success=theHeap.change(value, value2); if(!success){ System.out.println("Invalid index"); } break; default:break; } theHeap.displayHeap(); } } }
虽然没有写出堆排序的代码,但还是说一下堆排序的效率吧,尽管它比快速排序略慢,但它比快速排序优越的一点是它对初始数据的分布不敏感。在关键字值按某种排列顺序的情况下,快速排序运行的时间复杂度可以降低到O(N*N)级,然而堆排序对任意排列的数据,其排序的时间复杂度都是O(N*logN)
相关文章推荐
- 数据结构实验之图论四:迷宫探索
- 【2015/11/21】 数据结构学习日志_Day17 双端链表
- leetcode之Rotate Array
- redis数据结构-链表
- 双向链表
- 数据结构与算法(4)--队列
- 机器学习模型数据结构:logistic regression, neural network, convolutional neural network
- 数据结构学习(C++)—二叉树
- 深度优先搜索——毕业BG
- 黑马程序员—Java基础—java基础语法:数据结构,运算符,选择结构,循环结构
- 数据结构基础6.3:最小生成树MST(Prim、Kruskal)
- 用c语言实现二分法查找表格【数据结构】
- 数据结构——建立单向链表(java实现)
- MySQL索引背后的数据结构及算法原理
- 二叉树
- 数据结构基础6.2:图的遍历
- 数据结构之 --- 树的应用(并查集)
- 几种查找数组的前K个最小值的算法
- 数据结构
- javascript数据结构之双链表插入排序实例详解