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 }

时间: 2024-10-12 10:08:23

JAVA数据结构--优先队列(堆实现)的相关文章

java数据结构和算法10(堆)

这篇我们说说堆这种数据结构,其实到这里就暂时把java的数据结构告一段落,感觉说的也差不多了,各种常见的数据结构都说到了,其实还有一种数据结构是"图",然而暂时对图没啥兴趣,等有兴趣的再说:还有排序算法,emmm....有时间再看看吧! 其实从写数据结构开始到现在让我最大的感触就是:新手刚开始还是不要看数据结构为好,太无聊太枯燥了,很容易让人放弃:可以等用的各种框架用得差不多了之后,再回头静下心来搞搞数据结构还是挺有趣的:废话不多说,开始今天的内容: 1.二叉树分类 树分为二叉树和多叉

0038数据结构之堆和优先队列

优先队列:出队顺序和入队顺序无关,而是和优先级有关(优先级高的先出队) 如果使用普通线性结构或者顺序线性结构实现优先队列,出队或者入队总有一方是O(n)级别的:如果使用堆实现优先队列,能使入队和出队的时间复杂度都是O(logn),效率是极高的. 二叉堆是一颗完全二叉树,不一定是满二叉树,但是确实节点的那部分一定是在整棵树的右下侧.满足的规律:1)根节点最大, 2)确实节点的那部分在整棵树的右下侧.(低层次的节点不一定大于高层次的节点) 下图是一颗最大堆: 可以用数组存储: 从数组1位置开始存储:

数据结构学习——堆

1 基本介绍 堆数据结构是一种数组对象,它可以被视为一颗完全二叉树.堆的访问可以通过三个函数来进行即, parent(i) return floor(i/2); left(i) return 2i; right(i) return 2i + 1; left操作可以通过一步左移操作完成,right操作可以通过左移并在地位+1实现,parent操作则可以通过把i右移一位得到.在实现中通常会使用宏或者内联函数来实现这三个操作. 二叉堆有两种,最大堆和最小堆.对于最大堆有 A[i] >= A[left(

java数据结构与算法之(Queue)队列设计与实现

[版权申明]转载请注明出处(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53375004 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) java数据结构与算法之栈设计与实现 java数据结构

数据结构--优先队列(堆排序)

数据结构--优先队列(堆排序) 优先队列:不是先进先出啦,下面的代码是大顶堆,大的先出. 在之前理解堆排序的基础上,在来理解优先队列. 还是用这个公式: leftNo = parentNo*2+1 rightNo = parentNo*2+2 parentNo = (nodeNo-1)/2 每次进队列是从最后进,在慢慢上浮. 每次出队列,堆顶先出,在把队尾调到堆顶,在下浮. 上代码 package sy181002; import java.util.Arrays; /** * 优先队列 * *

Java数据结构和算法(二)——数组

数组的用处是什么呢?--当你需要将30个数进行大小排列的时候,用数组这样的数据结构存储是个很好的选择,当你是一个班的班主任的时候,每次要记录那些学生的缺勤次数的时候,数组也是很有用.数组可以进行插入,删除,查找等. 1)创建和内存分配 Java中有两种数据类型,基本类型和对象类型,也有人称为引用类型,Java中把数组当成对象,创建数组时使用new操作符. int array[] = new int[10]; 既然是对象,那么array便是数组的一个引用,根据Java编程思想(一) -- 一切都是

Java当中的堆与栈详细解析

总结第一句话:Java语言使用内存的时候,栈内存主要保存以下内容:基本数据类型和对象的引用,而堆内存存储对象,栈内存的速度要快于堆内存.总结成一句话就是:引用在栈而对象在堆. Java疯狂讲义的一段对话作为开场白. 一个问题:为什么有栈内存和堆内存之分? 答:当一个方法执行时,每个方法都会简历自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁.因此,所有在方法中创建一个对象时,这个对象将被保存到运行时数据区中,以便利用(因为对象的创建成

Java数据结构和算法之链表

三.链表 链结点 在链表中,每个数据项都被包含在'点"中,一个点是某个类的对象,这个类可认叫做LINK.因为一个链表中有许多类似的链结点,所以有必要用一个不同于链表的类来表达链结点.每个LINK对象中都包含一个对下一个点引用的字段(通常叫做next)但是本身的对象中有一个字段指向对第一个链结点的引用. 单链表 用一组地址任意的存储单元存放线性表中的数据元素. 以元素(数据元素的映象)  + 指针(指示后继元素存储位置)  = 结点(表示数据元素 或 数据元素的映象) 以"结点的序列&q

java数据结构与算法之顺序表与链表深入分析

转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/52953190 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 ??数据结构与算法这门学科虽然在大学期间就已学习过了,但是到现在确实也忘了不少,因此最近又重新看了本书-<数据结构与算法分析>加上之前看的<java数据结构>也算是对数据结构的进一步深入学习了,于是也就打算