heap definition
1.堆是完全二叉树
2.所有父节点一定要大于子节点(大顶堆)
1.heapify
/**
*递归写法:二叉树的后序遍历
* @param tree :存储堆的数组
* @param n : 数组的长度
* @param i : 数组索引,表示此时的节点:表示对哪一个点进行heapify操作
*/
public void heapify(int[] tree , int n , int i){
if(i >= n) return;//递归终止条件
int c1 = 2 * i + 1;//此时节点的左子节点
int c2 = 2 * i + 2;//此时节点的右子节点
int max = i;//假设刚开始最大值节点是该节点
//看看最大值是不是左子节点
if(c1 < n && tree[c1] > tree[max]){
max = c1;
}
//看看最大值是不是右子节点
if(c2 < n && tree[c2] > tree[max]){
max = c2;
}
//如果最大值节点是其左子节点或者右子节点,进行swap
//如果最大值max就是跳出循环
if(max != i){
swap(tree,max,i);//max指向的是i的左子结点或者右子结点
//向下递归操作i的左子结点或者右子结点
heapify(tree,n,max);
}
}
private void swap(int[] tree, int i, int j) {
int tmp = tree[i];
tree[i] = tree[j];
tree[j] = tmp;
}
2. buildHeap
private void buildHeap(int[] tree , int n){
int lastNode = n - 1;//最后一个叶子结点
int parent = (lastNode - 1) / 2;//最后一个叶子结点的父亲结点
for(int i = parent ; i >= 0 ; i--){
heapify(tree,n,i);
}
}
3.heap sort
private void heapSort(int[] tree , int n){
//建堆
buildHeap(tree,n);
//堆排序
//每次都是:
//1.将堆的最后一个元素和堆顶元素进行swap(堆顶元素是max值)
//2.删除数组的最后一个元素,可以不用真正的去删除它,用i表示
//3.交换完后对堆顶元素heapify操作
for(int i = n - 1 ; i >= 0 ; i--){
swap(tree,i,0);
//一开始的写法:heapify(tree,n,0);
//只要让n改成i,i是不断减少的不用进行最后一个元素的砍断操作
heapify(tree,i,0);
}
}
4.summary
import java.util.Arrays;
import java.util.HashMap;
import java.util.function.Predicate;
/**
* @author zzyuan
* @date 2021/11/20 - 14:55
*/
public class Demo {
/**
*
* @param tree :存储堆的数组
* @param n : 数组的长度,节点的个数
* @param i : 数组索引,表示此时的节点
*/
public void heapify(int[] tree , int n , int i){
if(i >= n) return;//递归终止条件
int c1 = 2 * i + 1;//此时的节点的左子节点
int c2 = 2 * i + 2;//此时的节点的右子节点
int max = i;//假设刚开始最大值节点是该节点
//看看最大值是不是左子节点
if(c1 < n && tree[c1] >tree[max]){
max = c1;
}
//看看最大值是不是右子节点
if(c2 < n && tree[c2] > tree[max]){
max = c2;
}
//如果最大值节点是其左子节点或者右子节点,进行swap
if(max != i){
swap(tree,max,i);
//向下递归操作
heapify(tree,n,max);
}
}
private void buildHeap(int[] tree , int n){
int lastNode = n - 1;
int parent = (lastNode - 1) / 2;
for(int i = parent ; i >= 0 ; i--){
heapify(tree,n,i);
}
}
private void heapSort(int[] tree , int n){
//建堆
buildHeap(tree,n);
//堆排序
//每次都是:
//1.将堆的最后一个元素和堆顶元素进行swap(堆顶元素是max值)
//2.删除数组的最后一个元素,可以不用真正的去删除它,用i表示
//3.交换完后对堆顶元素heapify操作
for(int i = n - 1 ; i >= 0 ; i--){
swap(tree,i,0);
heapify(tree,i,0);
}
}
private void swap(int[] tree, int i, int j) {
int tmp = tree[i];
tree[i] = tree[j];
tree[j] = tmp;
}
public static void main(String[] args) {
int[] tree = {2,5,3,1,10,4};
int n = 6;
Demo demo = new Demo();
// demo.buildHeap(tree,tree.length);
demo.heapSort(tree,n);
System.out.println(Arrays.toString(tree));
}
}