堆排序和优先级队列

来源:互联网 发布:python开发环境下载 编辑:程序博客网 时间:2024/05/18 01:13

堆的定义:n个元素的序列(k1,k2,……kn)按照完全二叉树形排列,当且仅当满足下列关系时,称之为堆

 

小根堆  

ki<k2i

ki<k2i+1

大根堆  

ki>k2i

ki>k2i+1

(i=1,2,…...n/2)

 

可将堆序列看成完全二叉树,则堆顶元素(完全二叉树的根)必为序列中n个元素的最小值或最大值

 

堆排序:将无序序列建成一个堆,得到关键字最小(或最大)的记录;输出堆顶的最小(大)值后,使剩余的n-1个元素又重新建成一个堆,则可得到n个元素的次小值;重复执行,得到一个有序序列,这个过程叫~

堆排序需解决的两个问题:

 1.如何由一个无序序列建成一个堆?

 2.如何在输出堆顶元素之后,调整剩余元素,使之成为一个新的堆?

第二个问题解决方法——筛选

 方法:输出堆顶元素之后,以堆中最后一个元素替代之;然后将根结点值与左、右子树的根结点值进行比较,并与其中小者进行交换;重复上述操作,直至叶子结点,将得到新的堆,称这个从堆顶至叶子的调整过程为“筛选”



第一个问题解决方法

 方法:从无序序列的第n/2个元素(即此无序序列对应的完全二叉树的最后一个非终端结点)起,至第一个元素止,进行反复筛选


 

java实现:

package ctgu.sugite.content.character06;import java.util.Arrays;public class Heap_Sort {private void heapSort() {buildMaxHeap();for (int i = this.size; i > 1; i--) {swap(0, i - 1);this.size--;maxHeapify(1);}}//堆排序private void buildMaxHeap() {for (int i = this.length / 2; i > 0; i--)maxHeapify(i);}//建初堆private void maxHeapify(int i) {int largest = i;int l = i << 1;int r = l + 1;if (l <= this.size && this.a[i - 1] < this.a[l - 1])largest = l;if (r <= this.size && this.a[largest - 1] < this.a[r - 1])largest = r;if (largest != i) {swap(i - 1, largest - 1);maxHeapify(largest);}}//重建堆private void swap(int i, int j) {a[i] = a[i] - a[j];a[j] = a[i] + a[j];a[i] = a[j] - a[i];}public Heap_Sort(int[] a) {this.a = a;this.length = a.length;this.size = this.length;}public static void main(String[] args) {int[] x = { 9, 8, 7, 6, 0, 4, 3, 2, 1, 0 };Heap_Sort hs = new Heap_Sort(x);hs.heapSort();System.out.println(Arrays.toString(x));}private int[] a;// 待排序数组private int length;// 数组长度private int size;// 大根堆结点数目}


优先级队列是一种用来维护由一组元素构成的集合S的数据结构,这一组元素中的每一个都有一个关键字key,一个最大优先级队列支持以下操作:

MAXIMUM(S):返回S中具有最大关键字的元素。

private int heapMaximum() {return a[0];}

EXTRACT-MAX(S):去掉并返回S中的具有最大关键字的元素。

private int heapExtractMax() throws Exception {if (this.size < 1)throw new Exception("heap underflow");int max = a[0];a[0] = a[this.size--];maxHeapify(1);return max;}

INCREASE-KEY(S,x,k):将元素x的关键字的值增加至k,这里的k值不能小于x的原关键字的值。

private void heapIncreaseKey(int i, int key) throws Exception {if (key < a[i - 1])throw new Exception("new key is smaller than current key");a[i - 1] = key;while (i > 1 && a[i / 2 - 1] < a[i - 1]) {swap(i / 2 - 1, i);i /= 2;}}

INSERT(S,x):把元素x插入集合S。这一操作可写为S←S∪{x}。

private void maxHeapInsert(int key) throws Exception {a[++this.size] = Integer.MIN_VALUE;heapIncreaseKey(this.size, key);}

以上代码片段可直接加入到堆排序代码中使用。

最大优先级队列的一个应用是在一台分时计算机上进行作业调度。