Loading

JAVA数据结构--优先队列(堆实现)

优先队列(堆)的定义

英语:Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。在队列中,调度程序反复提取队列中第一个作业并运行,因为实际情况中某些时间较短的任务将等待很长时间才能结束,或者某些不短小,但具有重要性的作业,同样应当具有优先权。堆即为解决此类问题设计的一种数据结构。

我个人比较通俗的理解就是比如我们平常下载视频看,我们打算下载两部视频,一部2G,一部只有200M。优先队列的思想就是先下载那部体积较小的视频,这样也比较合理,可以下完200M后看的同时再下2G的视频。

 

堆是一颗被完全填满的二叉树,唯一可能的例外是在最底层。所以堆具有两个性质——堆序性和结构性。一个高为h的完全二叉树有2h或2h-1个节点,并且堆中每一个节点X的父亲的值小于或等于X中的关键字,所以堆的最小值总可以在根中找到。

堆的构造实现

private static final int DEFAULT_CAPACITY=10;//定义堆的大小
private int currentSize;//当前实际堆的大小
private T [] array;    //数组表示堆中元素

 

 1 public BinaryHeap(int capacity) {//初始化堆数组
 2         currentSize=0;
 3         array=(T[])new Comparable[capacity+1];
 4 }
 5 public BinaryHeap(T[] items) {
 6         currentSize=items.length;
 7         array=(T[])new Comparable[(currentSize+2)*11/10];
 8         
 9         int i=1;
10         for(T item:items)
11             array[i++]=item;//堆数组赋值
12         buildHeap();
13 }

 

private void buildHeap() {
    for(int i=currentSize/2;i>0;i--)//逐层下滤
        percolateDown(i);
}

注意!用数组实现堆时,元素的下标是从1开始,不是从0开始。原因是因为当插入的元素是比堆顶还小的元素时,我们不需要对堆做任何操作即可把堆冒出。

元素插入

 1 public void insert(T x) {
 2         if(currentSize==array.length-1)
 3             enlargeArray(array.length*2+1);//堆扩容
 4         int hole=++currentSize;    //空穴表示的数组下标
 5         /*
 6          * hole/2是当前空穴的父节点的数组下标,如果x比父节点的元素小,则父节点元素下沉,空穴上冒
 7          * */
 8         for(array[0]=x;x.compareTo(array[hole/2])<0;hole/=2)
 9             array[hole]=array[hole/2];    //元素交换
10         array[hole]=x;
11 }

 

 

 

删除最小元

 删除最小元基本的思想是将最小元置为空穴,再将堆的最后一个元素放入其中,则此时的堆是不合法的,我们需要做的就是将此时的堆顶元素下沉到合适的位置。

1 public T deleteMin() throws Exception {
2         if(isEmpty())
3             throw new Exception();
4         T minItem=findMin();//获取最小元
5         array[1]=array[currentSize--];//取出最后一个元素
6         percolateDown(1);//元素下滤
7         return minItem;
8 }

 

 1 private void percolateDown(int hole) {//下滤元素
 2         int child;
 3         T tmp=array[hole];
 4         for(;hole*2<=currentSize;hole=child) {
 5             child=hole*2;//孩子节点的下标
 6             if(child!=currentSize&&
 7                     array[child+1].compareTo(array[child])<0)//找出较小的孩子节点
 8                 child++;
 9             if(array[child].compareTo(tmp)<0)//逐层下滤
10                 array[hole]=array[child];//元素替换
11             else
12                 break;
13         }
14         array[hole]=tmp;
15 }

 

全部代码实现(数据结构与算法分析中的demo)

  1 // BinaryHeap class
  2 //
  3 // CONSTRUCTION: with optional capacity (that defaults to 100)
  4 //               or an array containing initial items
  5 //
  6 // ******************PUBLIC OPERATIONS*********************
  7 // void insert( x )       --> Insert x
  8 // Comparable deleteMin( )--> Return and remove smallest item
  9 // Comparable findMin( )  --> Return smallest item
 10 // boolean isEmpty( )     --> Return true if empty; else false
 11 // void makeEmpty( )      --> Remove all items
 12 // ******************ERRORS********************************
 13 // Throws UnderflowException as appropriate
 14 
 15 /**
 16  * Implements a binary heap.
 17  * Note that all "matching" is based on the compareTo method.
 18  * @author Mark Allen Weiss
 19  */
 20 public class BinaryHeap<AnyType extends Comparable<? super AnyType>>
 21 {
 22     /**
 23      * Construct the binary heap.
 24      */
 25     public BinaryHeap( )
 26     {
 27         this( DEFAULT_CAPACITY );
 28     }
 29 
 30     /**
 31      * Construct the binary heap.
 32      * @param capacity the capacity of the binary heap.
 33      */
 34     public BinaryHeap( int capacity )
 35     {
 36         currentSize = 0;
 37         array = (AnyType[]) new Comparable[ capacity + 1 ];
 38     }
 39     
 40     /**
 41      * Construct the binary heap given an array of items.
 42      */
 43     public BinaryHeap( AnyType [ ] items )
 44     {
 45             currentSize = items.length;
 46             array = (AnyType[]) new Comparable[ ( currentSize + 2 ) * 11 / 10 ];
 47 
 48             int i = 1;
 49             for( AnyType item : items )
 50                 array[ i++ ] = item;
 51             buildHeap( );
 52     }
 53 
 54     /**
 55      * Insert into the priority queue, maintaining heap order.
 56      * Duplicates are allowed.
 57      * @param x the item to insert.
 58      */
 59     public void insert( AnyType x )
 60     {
 61         if( currentSize == array.length - 1 )
 62             enlargeArray( array.length * 2 + 1 );
 63 
 64             // Percolate up
 65         int hole = ++currentSize;
 66         for( array[ 0 ] = x; x.compareTo( array[ hole / 2 ] ) < 0; hole /= 2 )
 67             array[ hole ] = array[ hole / 2 ];
 68         array[ hole ] = x;
 69     }
 70 
 71 
 72     private void enlargeArray( int newSize )
 73     {
 74             AnyType [] old = array;
 75             array = (AnyType []) new Comparable[ newSize ];
 76             for( int i = 0; i < old.length; i++ )
 77                 array[ i ] = old[ i ];        
 78     }
 79     
 80     /**
 81      * Find the smallest item in the priority queue.
 82      * @return the smallest item, or throw an UnderflowException if empty.
 83      */
 84     public AnyType findMin( )
 85     {
 86         if( isEmpty( ) )
 87             throw new UnderflowException( );
 88         return array[ 1 ];
 89     }
 90 
 91     /**
 92      * Remove the smallest item from the priority queue.
 93      * @return the smallest item, or throw an UnderflowException if empty.
 94      */
 95     public AnyType deleteMin( )
 96     {
 97         if( isEmpty( ) )
 98             throw new UnderflowException( );
 99 
100         AnyType minItem = findMin( );
101         array[ 1 ] = array[ currentSize-- ];
102         percolateDown( 1 );
103 
104         return minItem;
105     }
106 
107     /**
108      * Establish heap order property from an arbitrary
109      * arrangement of items. Runs in linear time.
110      */
111     private void buildHeap( )
112     {
113         for( int i = currentSize / 2; i > 0; i-- )
114             percolateDown( i );
115     }
116 
117     /**
118      * Test if the priority queue is logically empty.
119      * @return true if empty, false otherwise.
120      */
121     public boolean isEmpty( )
122     {
123         return currentSize == 0;
124     }
125 
126     /**
127      * Make the priority queue logically empty.
128      */
129     public void makeEmpty( )
130     {
131         currentSize = 0;
132     }
133 
134     private static final int DEFAULT_CAPACITY = 10;
135 
136     private int currentSize;      // Number of elements in heap
137     private AnyType [ ] array; // The heap array
138 
139     /**
140      * Internal method to percolate down in the heap.
141      * @param hole the index at which the percolate begins.
142      */
143     private void percolateDown( int hole )
144     {
145         int child;
146         AnyType tmp = array[ hole ];
147 
148         for( ; hole * 2 <= currentSize; hole = child )
149         {
150             child = hole * 2;
151             if( child != currentSize &&
152                     array[ child + 1 ].compareTo( array[ child ] ) < 0 )
153                 child++;
154             if( array[ child ].compareTo( tmp ) < 0 )
155                 array[ hole ] = array[ child ];
156             else
157                 break;
158         }
159         array[ hole ] = tmp;
160     }
161 
162         // Test program
163     public static void main( String [ ] args )
164     {
165         int numItems = 10000;
166         BinaryHeap<Integer> h = new BinaryHeap<>( );
167         int i = 37;
168 
169         for( i = 37; i != 0; i = ( i + 37 ) % numItems )
170             h.insert( i );
171         for( i = 1; i < numItems; i++ )
172             if( h.deleteMin( ) != i )
173                 System.out.println( "Oops! " + i );
174     }
175 }
View Code

 

posted @ 2017-12-07 21:49  xpang0  阅读(8361)  评论(0编辑  收藏  举报