数据结构之堆
2015-09-10 13:13
941 查看
堆同一般二叉树一样可采用顺序存储和链接存储,但是由于堆是一颗完全二叉树,所以适合采用顺序存储,这样才能够充分利用存储空间。
对堆进行顺序存储时,首先要对堆中的所有结点进行编号,然后再以编号为下标存储到指定的数组的对应元素中。为了利用数组的0号元素,让堆中结点的编号从0开始,顺序为从上到下,从左到右,若堆中含有n个结点,则编号的范围为0~n-1。
堆中编号为0~(n/2)-1(n/2向下取整)的结点为分支结点,编号为n/2(向下取整)~n-1的结点为叶子结点;当n为奇数的时候则每个分支结点既有左孩子也有右孩子,当n为偶数的时候则编号为最大分支结点只有左孩子没有右孩子;对于每一个编号为i的分支结点,其左孩子结点的编号为2i+1,右孩子结点的编号为2i+2;除编号为0的结点外,对于其他编号为i的结点,其双亲结点的编号为(i-1)/2(向下取整)。
对堆进行顺序存储时,首先要对堆中的所有结点进行编号,然后再以编号为下标存储到指定的数组的对应元素中。为了利用数组的0号元素,让堆中结点的编号从0开始,顺序为从上到下,从左到右,若堆中含有n个结点,则编号的范围为0~n-1。
堆中编号为0~(n/2)-1(n/2向下取整)的结点为分支结点,编号为n/2(向下取整)~n-1的结点为叶子结点;当n为奇数的时候则每个分支结点既有左孩子也有右孩子,当n为偶数的时候则编号为最大分支结点只有左孩子没有右孩子;对于每一个编号为i的分支结点,其左孩子结点的编号为2i+1,右孩子结点的编号为2i+2;除编号为0的结点外,对于其他编号为i的结点,其双亲结点的编号为(i-1)/2(向下取整)。
package org.heap.cn; /** * 堆分为小根堆和大根堆(均为二叉树) * 1)若树根节点存在孩子,则根节点的值小于等于左孩子节点的值 * 2)若树根节点存在右孩子,则根节点的值小于等于右孩子的节点的值 * 3)以左,右孩子为根的子树又各是一个堆 * 大根堆的定义与上述差不多,大于等于 * @author Administrator * */ public interface HeapADT { /** * 向堆中插入一个元素 * @param obj */ void insert(final Object obj); /*** * 从堆中删除堆顶元素并返回 * @return */ Object delete(); /*** * 返回堆中元素的个数 */ int size(); /*** * 按照二叉树的广义表格输出一个堆 */ void output(); /** * 堆是否为空 * @return */ boolean isEmpty(); /*** * 清除一个堆,,使之成为空堆 */ void clear(); }
package org.heap.cn; public class SequenceHeap implements HeapADT { final int maxSize=10; private Object[] heapArray; private int length; //当前堆的实际长度 public SequenceHeap() { // TODO Auto-generated constructor stub length=0; heapArray=new Object[maxSize]; } public SequenceHeap(int n){ if(n<=0){ System.out.println("数组长度应大于0"); } length=0; heapArray=new Object ; } @Override public void insert(Object obj) { if(length==heapArray.length){ Object[] p=new Object[2*length]; for(int i=0;i<length;i++){ p[i]=heapArray[i]; } heapArray=p; } heapArray[length++]=obj;//向数组length的位置上添加新元素 int i=length-1; //指向待调整的元素位置,初始指向新元素所在的堆尾 while(i!=0){ int j=(i-1)/2; if(((Comparable)obj).compareTo((Comparable)heapArray[j])>=0){ break; //找到新元素插入位置就退出循环 } heapArray[i]=heapArray[j]; //双亲元素下移 i=j; } heapArray[i]=obj; } @Override public Object delete() { // TODO Auto-generated method stub if(length==0){ System.out.println("当前的堆为空,不能删除"); return null; } Object temp=heapArray[0]; //temp为堆顶元素 length--; if(length==0){ return temp; } Object x=heapArray[length]; int i=0; int j=1; while(j<=length-1){ if(j<length-1 && ((Comparable)heapArray[j]).compareTo(heapArray[j+1])>0){ j++; } if(((Comparable)heapArray[j]).compareTo(heapArray[j+1])<=0){ break; } heapArray[i]=heapArray[j]; i=j; j=2*i+1; } heapArray[i]=x; return temp; } @Override public int size() { // TODO Auto-generated method stub return 0; } @Override public void output() { // TODO Auto-generated method stub outPut(0); System.out.println(); } private void outPut(int rt){ if(rt<length){ System.out.println(heapArray[rt]); if(2*rt+1<length){ System.out.println('('); outPut(2*rt+1); if(2*rt+2<length){ System.out.println(','); } outPut(2*rt+2); System.out.println(')'); } } } @Override public boolean isEmpty() { // TODO Auto-generated method stub return length==0; } @Override public void clear() { // TODO Auto-generated method stub length=0; } }