1. 堆
堆,也叫做优先队列。而其实质上是一颗完全二叉树,而且其每个非叶节点的值都大于或等于它左右孩子的值(大根堆),或者小于等于它左右孩子的值(小根堆)。而之所以称之为优先队列,是因为在队列中我们按存入队列的先后顺序取出元素,而在堆中我们按照节点的优先级别取出元素(显然,根节点具有最大优先级)。
以大根堆为例,堆的主要操作是插入和删除最大元素(元素值本身为优先级键值,大元素享有高优先级)。在插入或者删除操作之后,我们必须保持该实现应有的性质: 1. 完全二叉树 2. 每个节点值都大于或等于它的子节点。
所以堆的插入步骤(上滤):
1.将新元素增加到堆的末尾
2.按照优先顺序,将新元素与其父节点比较,如果新元素小于父节点则将两者交换位置。
3.不断进行第2步操作,直到不需要交换新元素和父节点,或者达到堆顶
4.最后通过得到一个最小堆
堆的删除步骤(下滤):
1.删除堆顶元素(通常是将堆顶元素放置在数组的末尾)
2.比较左右子节点,将小的元素上调。
3.不断进行步骤2,直到不需要调整或者调整到堆底
2.堆排序
排序的过程:首先将待排序系列的记录构造成一个大根堆,然后将堆定记录移走,继续将剩下的记录再调整成大根堆,如此循环,直到堆中只有一个记录为止。
package heap_sort;
import java.util.Arrays;
import java.util.Scanner;
public class HeapSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int[] arr = new int[8];
for(int i = 0; i < arr.length; i++)
arr[i] = sc.nextInt();
Heapsort(arr);
System.out.println(Arrays.toString(arr));
sc.close();
}
private static void Heapsort(int[] arr) {
for(int i = 0; i < arr.length; i++) {
CreateMaxHeap(arr,arr.length-1-i);
Swap(arr,0,arr.length-1-i);
}
}
private static void CreateMaxHeap(int[] arr, int LastIndex) {
for(int i = (LastIndex - 1) / 2; i >= 0; i--) {
int k = i;
while(k * 2 + 1 <= LastIndex) {
int leftChild = k * 2 +1;
if(leftChild < LastIndex) {
if(arr[leftChild] < arr[leftChild + 1])
leftChild++;
}
if(arr[k] < arr[leftChild])
Swap(arr, k, leftChild);
else
break;
}
}
}
private static void Swap(int[] arr, int a, int b) {
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
}
要注意的是完全二叉树中,设最后节点的键值为lastIndex,其父节点为(lastIndex-1)/2.也就是说从最后一个有孩子节点的父节点开始比较,逐步构建大根堆,这样会比较节省效率。
参考文献:
1. http://www.cnblogs.com/vamei/archive/2013/03/20/2966612.html