数据结构之堆

堆的定义与基本概念

堆是一种特殊的完全二叉树,也叫优先级队列,满足以下性质之一:

  • 最大堆:任意节点的值大于或等于其子节点的值(根节点为最大值)。
  • 最小堆:任意节点的值小于或等于其子节点的值(根节点为最小值)。

堆的存储方式

堆通常通过数组实现,利用完全二叉树的特性进行索引映射:

  • 对于节点 i(从 0 开始计数):
    • 父节点索引:(i - 1) // 2
    • 左子节点索引:2i + 1
    • 右子节点索引:2i + 2

堆的操作

插入元素(上浮)向上调整多用于插入

  1. 将新元素添加到数组末尾。
  2. 比较新元素与其父节点的值,若违反堆性质则交换。
  3. 重复上浮过程直至满足堆性质。

删除堆顶元素(下沉)向下调整多用于构建堆和删除元素

  1. 交换堆顶与数组末尾元素,并删除末尾元素。
  2. 从堆顶开始,比较当前节点与子节点的值,若违反堆性质则与较大(最大堆)或较小(最小堆)的子节点交换。
  3. 重复下沉过程直至满足堆性质。

堆的构建

时间复杂度 :O(n)(自底向上调整)。

  1. 从最后一个非叶子节点开始(索引 n//2 - 1)。
  2. 对每个节点执行下沉操作,确保子树满足堆性质。

代码示例(Java)

java 复制代码
import java.util.ArrayList;
import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: zhany
 * Date: 2025-10-24
 * Time: 19:48
 */
public class Piorory {
    int[] elem;
    int usedSize;
    public Piorory(){
        this.elem = new int[10];
    }
    public void initElem(int[] array) {
        for (int i = 0; i < array.length; i++) {
            this.elem[i] = array[i];
            this.usedSize++;
        }
    }
    public void creatHeap(){
        for (int parent = (this.usedSize-2)/2; parent >=0; parent--) {
            siftDown(parent,this.usedSize);
        }
    }
//向下调整主要是用于构建堆和删除顶部元素
    private void siftDown(int parent, int usedSize) {
        int child = 2*parent +1;
        while(child<usedSize){
            if(child+1<usedSize && elem[child] <elem[child+1]){
                child ++;
            }
            if(elem[child] >elem[parent]){
                swap(elem,child,parent);
                parent = child;
                child = 2*parent+1;
            } else{
                break;
            }
        }
    }

    private void swap(int[]elem,int child, int parent) {
        int tmp = elem[child];
        elem[child] = elem[parent];
        elem[parent] = tmp;
    }
    //向上主要是用于插入元素
    public void shifUp(int child){
        int parent = (child-1)/2;
        while(parent >= 0){
            if (elem[child] > elem[parent]) {
                swap(elem,child,parent);
                child = parent;
                parent = (child -1)/2;
            } else{
                break;
            }
        }
    }

    public void offer(int val){
        if(isFull()){
        elem = Arrays.copyOf(elem,2*elem.length);
    }
        elem[usedSize] = val;
        shifUp(usedSize);
        usedSize++;
    }
    public  boolean isFull(){
        return  usedSize == elem.length;
    }
    public boolean isEmpty(){
        return usedSize == 0;
    }
    public int peek(){
        if (isEmpty()) {
            return -1;
        }
            return elem[0];
    }
    public void printHeap() {
        for (int i = 0; i < usedSize; i++) {
            System.out.print(elem[i] + " ");
        }
        System.out.println();
    }
}
相关推荐
倒头就睡的小比特5 天前
算法竞赛C++常用的STL
c++·算法
默_笙5 天前
🍙 给每个请求过安检:FastAPI 是怎么把校验写进类型注解的
python
小羊没烦恼!5 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
qq_426003965 天前
启动playwright录制codegen生成自动化测试脚本
python·自动化
虎头金猫5 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
长沙三为智能科技5 天前
家政小程序开发从0到上线:五阶段交付流程与验收清单
python
伞伞悦读5 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
猎头南楼5 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
只睡四小时5 天前
Canvas 弹道联机实战:700 行 + 固定时间步长
python·websocket·html5·游戏开发·canvas
m0_547486666 天前
《数据结构教程》全套 PPT课件2026
数据结构