前言
堆首先满足的条件是一棵完全二叉树。即丛上到下,从左到右依次添加节点。其次父节点大于子节点。
如上图所示:堆构成的数组是:
int[] arr={10,8,2,4,5,1}
对于8来说。索引是1。父节点的索引是0,左孩子的索引3,右孩子的索引是4。有如下的性质:
假设当前节点的索引是i。
父节点索引:index_parent=(i-1)/2。
左孩子节点索引:index_parent=2i+1
右孩子节点索引:index_parent=2i+2
提示:以下是本篇文章正文内容,下面案例可供参考
一、heapify
heapify就是调整节点,使局部符合堆的性质。即父节点>左节点 && 父节点>右节点
代码如下:
/**
*
* @param tree
* @param length 数组长度
* @param i 要调整的节点的索引
*/
private static void heapify(int[] tree,int length, int i) {
//递归出口
if (i >=length) {
return;
}
//获取左节点、右节点的索引
int c1 = 2 * i + 1;
int c2 = 2 * i + 2;
int max = i;
if (c1 < length && tree[c1] > tree[max]) {
max = c1;
}
if (c2 < length && tree[c2] > tree[max]) {
max = c2;
}
//获取到最大的节点的索引之后,开始交换值
if (max != i) {
swap(tree, max, i);
//递归heapify
heapify(tree,length, max);
}
}
测试如下:
public static void main(String[] args) {
int[] arr = {4, 10, 3,5,1,2};
heapify(arr,6,0);
System.out.println(Arrays.toString(arr));
}
二、构建堆
获取到最后一个节点,然后自下往上进行heapify即可。
/**
* 构建堆
*
* @param tree
* @param length 数组长度
*/
private static void build_heap(int[] tree, int length) {
int last_node = length - 1;
int parent = (last_node - 1) / 2;
for (int i = parent; i >= 0; i--) {
heapify(tree, length, i);
}
}
测试代码如下:
public static void main(String[] args) {
//int[] arr = {4, 10, 3,5,1,2};
int[] arr = {2, 5, 3,1,10,4};
build_heap(arr,6);
System.out.println(Arrays.toString(arr));//[10, 5, 4, 1, 2, 3]
}
三、堆排序
流程如下:
排序代码如下:
/**
* 第i个元素。其父节点的索引和左右节点的索引如下:
* index_parent=(i-1)/2
* index_left=2i+1
* index_right=2i+2
*
* @param arr
*/
private static void sort(int[] arr) {
build_heap(arr,arr.length);
for (int i = arr.length-1; i >= 0; i--) {
swap(arr, i, 0);
heapify(arr,i,0);
}
}
最终代码:
public class HeadSort {
public static void main(String[] args) {
//int[] arr = {4, 10, 3, 5, 1, 2};
//int[] arr = {4, 10, 3, 5, 1, 2};
int[] arr = {2, 5, 3,1,10,4};
//build_heap(arr,6);
sort(arr);
//heapify(arr, 6, 0);
System.out.println(Arrays.toString(arr));
}
/**
* 第i个元素。其父节点的索引和左右节点的索引如下:
* index_parent=(i-1)/2
* index_left=2i+1
* index_right=2i+2
*
* @param arr
*/
private static void sort(int[] arr) {
build_heap(arr,arr.length);
for (int i = arr.length-1; i >= 0; i--) {
swap(arr, i, 0);
heapify(arr,i,0);
}
}
/**
* 构建堆
*
* @param tree
* @param length 数组长度
*/
private static void build_heap(int[] tree, int length) {
int last_node = length - 1;
int parent = (last_node - 1) / 2;
for (int i = parent; i >= 0; i--) {
heapify(tree, length, i);
}
}
/**
* @param tree
* @param length 数组长度
* @param i 要调整的节点的索引
*/
private static void heapify(int[] tree, int length, int i) {
//递归出口
if (i >= length) {
return;
}
//获取左节点、右节点的索引
int c1 = 2 * i + 1;
int c2 = 2 * i + 2;
int max = i;
if (c1 < length && tree[c1] > tree[max]) {
max = c1;
}
if (c2 < length && tree[c2] > tree[max]) {
max = c2;
}
//获取到最大的节点的索引之后,开始交换值
if (max != i) {
swap(tree, max, i);
//递归heapify
heapify(tree, length, max);
}
}
private static void swap(int[] tree, int i, int j) {
int temp = tree[i];
tree[i] = tree[j];
tree[j] = temp;
}
}