排序算法之——优先队列经典实现(基于二叉堆)

 许多应用都需要处理有序的元素,但有时,我们不要求所有元素都有序,或是一定要一次就将它们排序,许多情况下,我们会收集这些元素里的最大值或最小值。

这种情况下一个合适的数据结构应该支持两种操作:插入元素、删除最大元素。

优先队列与栈和队列类似,但它有自己的奇妙之处。

在本文中,会讲解基于二叉堆的一种优先队列的经典实现方法(代码没有任何难度,主要是理解思想)。

 

一、关于堆

1、堆的定义:

 数据结构二叉堆能很好地实现优先队列的操作。在二叉堆中,每个元素都要保证大于等于另外两个位置的元素,相应的,这些位置的元素又至少要大于等于数组中的另外两个元素。

将所有元素画成一颗二叉树,就能很容易看出这种结构。

(图示1)

 

2、堆的算法:

在堆有序的过程中我们会遇到两种情况:

某个节点的优先级上升,我们需要由下至上恢复堆的顺序。

当某个节点的优先级下降,我们需要由上至下恢复堆的顺序。

在排序算法中,我们只通过私有辅助函数来访问元素:

复制代码
1     private void exch(int i, int j) { 2         Key temp = pq[i]; 3         pq[i] = pq[j]; 4         pq[j] = temp; 5     } 6  7     private boolean less(int i, int j) { 8         return pq[i].compareTo(pq[j]) < 0; 9     }
复制代码

 

①、由下至上的堆的有序化(上浮)

复制代码
1     private void swim(int k) {// 二叉堆 2         while (k > 1 && less(k / 2, k)) { 3             exch(k / 2, k); 4             k = k / 2; 5         } 6     }
复制代码

k/2即为k节点的父节点,当k大于k/2时交换两者,并继续与其父节点比较,直到找到合适的位置。

 

②、由上至下的堆的有序化(下沉)

复制代码
 1     private void sink(int k) {// 二叉堆  2         while (2 * k <= N) {  3             int j = 2 *

                    
                
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信