堆排序(最小堆)
Posted Java编程生涯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆排序(最小堆)相关的知识,希望对你有一定的参考价值。
一、定义和性质
定义:堆是按照完全二叉树的顺序结构存储在一个一维数组中,逻辑存储是完全二叉树,物理存储是数组。
性质:具有完全二叉树的顺序结构特性。
对于任意的节点,从上往下,父节点都小于左孩子和右孩子。
根节点最小的情况,称为最小堆。
用数组存储二叉堆,堆的顶点下标可以从0开始也可以从1开始。
堆顶下标从0开始:父节点=(i-1)/2、左子节点=2*i+1、右子节点=2*i+2,根节点等于0。
堆顶下标从1开始:父节点=i/2、左子节点=2*i、右子节点=2*i+1,根节点等于1。
调整原理:围绕最后一个叶子节点开始调整,也就是从33开始调整。
源数据图形:
最小堆图形:
二、排序源码
1、初始化
import java.util.Arrays;
/**
* 堆排序(最小堆)
* 计算方式: 父节点为(i-1)/2
* 左子节点为2*i+1
* 右子节点为2*i+2
* @author ouyangjun
*/
public class MinHeap {
private int[] elementData;
private int size;
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// 默认初始容量
public MinHeap() {
this(8);
}
// 指定初始容量
public MinHeap(int initialCapacity) {
if (initialCapacity > 0) {
elementData = new int[initialCapacity];
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
/**
* 扩容
* @param minCapacity
*/
private void grow(int minCapacity) {
if (minCapacity - elementData.length > 0) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
if (newCapacity - MAX_ARRAY_SIZE > 0) {
if (minCapacity < 0) {
throw new OutOfMemoryError();
}
newCapacity = minCapacity > MAX_ARRAY_SIZE ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
// 父节点
private int parent(int n) {
return (n-1)/2;
}
// 左子节点
private int left(int n) {
return 2 * n + 1;
}
// 右子节点
private int right(int n) {
return 2 * n + 2;
}
}
2、调整最小堆
private void downMinHeap(int[] array, int length) {
// 找到最后一个叶子节点的父节点
int parentIndex = parent(length);
for (int i = parentIndex; i >= 0; i--) {
downMinHeap(array, i, length);
}
}
private void downMinHeap(int[] array, int index, int length) {
// 先把第一个左孩子作为最小值
int min = left(index);
// 循环
while (min < length) {
if (min + 1 < length && array[min + 1] < array[min]) {
min += 1;
}
// 如果下标小于最小值,就不需要调整了,break
if (array[index] <= array[min]) {
break;
}
// 向下调整,交换
int temp = array[min];
array[min] = array[index];
array[index] = temp;
// 继续向下调整
index = min;
min = left(index);
}
}
3、添加
// 添加
public void add(int value) {
// 判断是否需要扩容
grow(size + 1);
// 插入元素
elementData[size++] = value;
// 构造最小堆
downMinHeap(elementData, size);
}
// 打印
public void print() {
System.out.print("[");
for (int i = 0; i < size; i++) {
System.out.print(elementData[i] + ", ");
}
System.out.print("]");
}
4、main方法测试
public static void main(String[] args) {
MinHeap heap = new MinHeap();
heap.add(14);
heap.add(56);
heap.add(55);
heap.add(45);
heap.add(11);
heap.add(3);
heap.add(21);
heap.add(76);
heap.add(23);
heap.add(34);
heap.add(43);
heap.add(33);
// 打印
heap.print();
}
长风破浪会有时,直挂云帆济沧海。
--李白《行路难·其一》
以上是关于堆排序(最小堆)的主要内容,如果未能解决你的问题,请参考以下文章