数据结构之堆(java)

来源:互联网 发布:数据分析 主成分分析 编辑:程序博客网 时间:2024/05/17 09:14

   记得以前已经实现过堆结构的一些操作,现在看看总有些不和谐,最近在看了看数据结构,觉得还是写的清晰具体一些,也可以方便以后的复习。下面介绍一下堆存在的一些意义。

   优先级队列可以用于计算机中的任务调度,在计算机中某些程序和活动需要比其他程序和活动先执行,因此需要给他们分配更高的优先级。

   另一个例子是在武器系统中,比如在一个海军巡洋舰系统中。会探测到许多对巡洋舰的威胁,比如来自飞机、导弹、潜水艇的攻击,需要为这些威胁分优先级。例如,离巡洋舰距离近的导弹就比距离远的飞机的优先级更高,这样对应的防范系统(例如地对空导弹)会首先对付它。

   堆是一种树,由它实现的优先级队列的插入和删除的时间复杂度是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;elselargeChild=rightChild;if(heapArray[largeChild].getKey()>heapArray[index].getKey())heapArray[index]=heapArray[largeChild];elsebreak;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);elsetrickleUp(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();elseSystem.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)

0 0
原创粉丝点击