堆结构和堆排序

1. 什么是堆 ?

2. 完全二叉树和数组前缀范围的对应

任何节点 i 的父亲节点 = (i - 1) / 2i 的左孩子 = i * 2 + 1i 的右孩子 = i * 2 + 2 

单独的变量size 来控制堆的大小, i * 2 + 1 < size 有左孩子、i * 2 + 2 < size 有右孩子

 

3. 向上调整大根堆、 向下调整大根堆

// 向上调整大根堆
public static void heapInsert(int[] arr, int child) {
int parent = (child - 1) / 2;
while (arr[child] > arr[parent]) {
swap(arr,child,parent);
child = parent;
parent = (child - 1) / 2;
}
}
// 向下调整大根堆
// 方法1:
public static void heapify1(int[] arr, int parent, int size) {
int child = parent * 2 + 1;
while (child < size) {
if (child + 1 < size && arr[child + 1] > arr[child]) {
child++;
}
if (arr[child] > arr[parent]) {
swap(arr,child,parent);
parent = child;
child = parent * 2 + 1;
}else {
break;
}
}
}
// 方法2:
public static void heapify2(int[] arr, int p, int size) {
int c = p * 2 + 1;
while (c < size) {
// 有左孩子
// 选左右最大孩子
int best = c + 1 < size && arr[c + 1] > arr[c] ? c + 1: c;
best = arr[best] > arr[p] ? best : p;
if (best == p) {
break;
}
swap(arr,best,p);
p = best;
c = p * 2 + 1;
}
}
public static void swap(int[] arr,int x,int y) {
int tmp = arr[x];
arr[x] = arr[y];
arr[y] = tmp;
}

 

4. 怎么把一颗完全二叉树改成 大/小根堆 ?

方法1:  向下调整建堆

方法2:  向上调整建堆

public static void createBigHeap(int[] arr) {
// 向上调整建堆
/*
for (int i = 0;i < arr.length;i++) {
heapInsert(arr,i);
} */
// 从最后一颗子树开始 向下调整建堆
int parent = (arr.length - 1 - 1) / 2;
for (int i = parent;i >= 0;i--) {
heapify2(arr,i,arr.length);
}
}

 

5. 堆的删除与插入

public int poll() {
int tmp = elem[0];
Swap(0,usedSize-1);
usedSize--;
siftDown(0,usedSize);
return tmp;
}

 

堆的插入:

public void offer(int data) {
if (elem.length == usedSize) {
this.elem = Arrays.copyOf(elem,elem.length*2);
}
elem[usedSize++] = data;
siftUp(usedSize-1);
}

 

6. 堆排序

大根堆排升序 小跟堆排降序

class Solution {
// 向上调整大根堆
public static void heapInsert(int[] arr, int child) {
int parent = (child - 1) / 2;
while (arr[child] > arr[parent]) {
swap(arr,child,parent);
child = parent;
parent = (child - 1) / 2;
}
}
// 向下调整大根堆
public static void heapify1(int[] arr, int parent, int size) {
int child = parent * 2 + 1;
while (child < size) {
if (child + 1 < size && arr[child + 1] > arr[child]) {
child++;
}
if (arr[child] > arr[parent]) {
swap(arr,child,parent);
parent = child;
child = parent * 2 + 1;
}else {
break;
}
}
}
public static void heapify2(int[] arr, int p, int size) {
int c = p * 2 + 1;
while (c < size) {
// 有左孩子
// 选左右最大孩子
int best = c + 1 < size && arr[c + 1] > arr[c] ? c + 1: c;
best = arr[best] > arr[p] ? best : p;
if (best == p) {
break;
}
swap(arr,best,p);
p = best;
c = p * 2 + 1;
}
}
public static void createBigHeap(int[] arr) {
// 向上调整建堆
/*
for (int i = 0;i < arr.length;i++) {
heapInsert(arr,i);
} */
// 向下调整建堆
int parent = (arr.length - 1 - 1) / 2;
for (int i = parent;i >= 0;i--) {
heapify2(arr,i,arr.length);
}
}
public static void swap(int[] arr,int x,int y) {
int tmp = arr[x];
arr[x] = arr[y];
arr[y] = tmp;
}
// 堆排序
public static void heapSort(int[] arr) {
createBigHeap(arr);
int n = arr.length;
while (n > 1) {
swap(arr,0,--n);
heapify1(arr,0,n);
}
}
public static int[] sortArray(int[] nums) {
if (nums.length > 1) {
heapSort(nums);
}
return nums;
}
public static void main(String[] args) {
int[] arr = {3,1,5,2,7};
sortArray(arr);
}
}

 

posted @   qyx1  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
点击右上角即可分享
微信分享提示