堆结构和堆排序
1. 什么是堆 ?
2. 完全二叉树和数组前缀范围的对应
任何节点 i 的父亲节点 = (i - 1) / 2,i 的左孩子 = i * 2 + 1,i 的右孩子 = 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); }
大根堆排升序 小跟堆排降序
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); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能