news 2026/4/23 2:01:10

二插堆的基本原理以及简单实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
二插堆的基本原理以及简单实现

文章目录

  • 堆(Heap)
    • 一、堆的基本概念
      • 1. 定义
      • 2. 特点
    • 二、二叉堆的特点
    • 二、堆的数组表示
  • 堆的相关操作
    • 创建堆的类型
    • 上浮(Heapify Up)
    • 下沉(Heapify Down)
    • 插入操作
    • 删除堆顶元素
    • 获取堆顶元素
  • 完整代码

堆(Heap)

一、堆的基本概念

1. 定义

  • 二叉堆是一种完全二叉树,它满足堆属性:
    • 最大堆:每个节点的值都大于或等于其子节点的值
    • 最小堆:每个节点的值都小于或等于其子节点的值

2. 特点

  • 二、二叉堆的特点

    1. 完全二叉树:除了最后一层,其他层都是满的,最后一层从左到右填充
    2. 堆属性:父节点和子节点之间保持特定的大小关系
    3. 数组表示:可以用数组高效存储,不需要指针

二、堆的数组表示

对于下标为 i 的节点:

  • 父节点:parent(i) = (i-1)/2
  • 左子节点:left(i) = 2*i + 1
  • 右子节点:right(i) = 2*i + 2

堆的相关操作

创建堆的类型

  1. 包括堆的数组

  2. 堆的类型(最大堆,最小堆)

  3. 获取节点的父节点,左孩子,右孩子

class Heap { public: vector<int> heap; bool isMaxHeap; // true表示最大堆, false表示最小堆 // 获取父节点索引 int parent(int index) { return (index - 1) / 2; } // 获取左孩子索引 int leftChild(int index) { return 2 * index + 1; } // 获取有孩子索引 int rightChild(int index) { return 2 * index + 2; } };

上浮(Heapify Up)

  1. 上浮操作用于在堆中插入新元素后,恢复堆的性质。

  2. 当我们向堆的末尾添加一个新元素时,可能会破坏堆的堆序性(父节点大于/小于子节点)。

  3. 上浮操作通过不断比较新元素与其父节点,必要时交换它们,直到堆性质恢复。

void heapifyUp(int index) { while (index > 0) { int parent = (index - 1) / 2; // 最大堆:如果当前节点大于父节点,交换 // 最小堆:如果当前节点小于父节点,交换 if (compare(heap[index], heap[parent])) { swap(heap[index], heap[parent]); index = parent; } else { break; } } }

下沉(Heapify Down)

  1. 下沉操作用于移除堆顶元素后,恢复堆的性质。

  2. 当我们移除堆顶元素时,通常将最后一个元素移到堆顶,然后通过下沉操作将其调整到合适位置,恢复堆性质。

void heapifyDown(int index) { int size = heap.size(); while (true) { int leftChild = 2 * index + 1; int rightChild = 2 * index + 2; int target = index; // 找到需要交换的子节点 if (leftChild < size && compare(heap[leftChild], heap[target])) { target = leftChild; } if (rightChild < size && compare(heap[rightChild], heap[target])) { target = rightChild; } // 如果需要交换,继续下沉 if (target != index) { swap(heap[index], heap[target]); index = target; } else { break; // 堆性质已满足 } } }

插入操作

  1. 插入操作向堆中添加新元素。首先将元素添加到数组末尾.
  2. 然后执行上浮操作将其调整到正确位置。
// 插入元素 void push(int value) { heap.push_back(value); heapifyUp(heap.size() - 1); }

删除堆顶元素

  1. 检查堆是否为空
  2. 保存堆顶元素
  3. 将最后一个元素移到堆顶
  4. 删除最后一个元素
  5. 如果堆不为空,对堆顶执行下沉操作
void pop() { if (heap.empty()) { cout << "堆为空,无法删除!" << endl; return; } heap[0] = heap.back(); heap.pop_back(); if (!heap.empty()) { heapifyDown(0); } }

获取堆顶元素

  1. 检查堆是否为空
  2. 返回数组的第一个元素
// 获取堆顶元素 int top() { if (heap.empty()) { cout << "堆为空!" << endl; return -1; } return heap[0]; }

完整代码

class Heap { public: vector<int> heap; bool isMaxHeap; // true表示最大堆, false表示最小堆 // 比较函数 bool compare(const int& a, const int& b) { return isMaxHeap ? a > b : a < b; } // 获取父节点索引 int parent(int index) { return (index - 1) / 2; } // 获取左孩子索引 int leftChild(int index) { return 2 * index + 1; } // 获取有孩子索引 int rightChild(int index) { return 2 * index + 2; } // 上浮操作 void heapifyUp(int index) { while (index > 0) { int parent = (index - 1) / 2; if (compare(heap[index], heap[parent])) { swap(heap[index], heap[parent]); index = parent; } else { break; } } } // 下沉操作 void heapifyDown(int index) { int size = heap.size(); while (true) { int leftChild = 2 * index + 1; int rightChild = 2 * index + 2; int target = index; // 找到当前节点、左子节点、右子节点中最符合堆性质的节点 if (leftChild < size && compare(heap[leftChild], heap[target])) { target = leftChild; } if (rightChild < size && compare(heap[rightChild], heap[target])) { target = rightChild; } // 如果当前节点不是最大的/最小的,交换并继续下沉 if (target != index) { swap(heap[index], heap[target]); index = target; } else { break; } } } // 构造函数 Heap(bool maxHeap = true) : isMaxHeap(maxHeap) {} // 从数组建堆的构造函数 Heap(const vector<int>& arr, bool maxHeap = true) : isMaxHeap(maxHeap) { heap = arr; // 从最后一个非叶子节点开始建堆 for (int i = heap.size() / 2 - 1; i >= 0; i--) { heapifyDown(i); } } // 插入元素 void push(int value) { heap.push_back(value); heapifyUp(heap.size() - 1); } // 删除堆顶元素 void pop() { if (heap.empty()) { cout << "堆为空,无法删除!" << endl; return; } heap[0] = heap.back(); heap.pop_back(); if (!heap.empty()) { heapifyDown(0); } } // 获取堆顶元素 int top() { if (heap.empty()) { cout << "堆为空!" << endl; return -1; } return heap[0]; } // 堆是否为空 bool empty() { return heap.empty(); } // 获取堆大小 int size() { return heap.size(); } // 获取堆类型 string getType() { return isMaxHeap ? "最大堆" : "最小堆"; } };
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/22 1:22:56

顶尖学术写作工具盘点:8款平台助你提升论文质量与规范性

工具核心特点速览 工具名称 核心优势 适用场景 数据支撑 aibiye 全流程覆盖降重优化 从开题到答辩的一站式需求 支持20万字长文逻辑连贯 aicheck 院校规范适配模板化输出 国内本硕博论文框架搭建 覆盖90%高校格式要求 秒篇 3分钟文献综述生成 紧急补文献章节 知…

作者头像 李华
网站建设 2026/4/21 23:28:59

力扣题解

目录 410.分割数组的最大值 4.寻找两个正序数组的中位数 51.N皇后 410.分割数组的最大值 这个题可以运用二分答案的算法来解题。定义一个左指针和一个右指针&#xff0c;令左指针等于数组的最大值&#xff0c;令右指针等于数组所有数之和。即最终的结果一定在他们之间。 lo…

作者头像 李华
网站建设 2026/4/22 17:56:17

毕设项目 基于大数据的K-means广告效果分析

基于大数据的K-means广告效果分析 项目运行效果&#xff1a; 毕业设计 基于大数据的K-means广告效果分析&#x1f9ff; 项目分享:见文末! 一、分析背景和目的 在大数据时代的背景下&#xff0c;广告主可以购买媒介变成直接购买用户&#xff0c;广告的精准投放对广告主、服务…

作者头像 李华
网站建设 2026/4/21 4:38:54

【计算机毕设选题推荐】基于Hadoop+Django的股市行情数据可视化分析平台 毕业设计 选题推荐 毕设选题 数据分析 机器学习

✍✍计算机毕设指导师** ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡有什么问题可以…

作者头像 李华
网站建设 2026/4/16 13:39:06

Unity学习笔记(十六)GUI总述

什么是GUI是即时模式游戏用户交互界面&#xff0c;在Unity中一般简称为GUI&#xff0c;是一个代码驱动的UI系统。GUI的主要作用1 作为程序员的调试工具&#xff0c;创建游戏内调试工具。2 为脚本组件创建自定义检视面板&#xff0c;创建新的编辑器窗口和工具扩展unity本身&…

作者头像 李华
网站建设 2026/4/19 14:48:33

ResCLIP

ResCLIP动机 现有方法&#xff08;如SCLIP、NACLIP&#xff09;通过将最后一层的标准交叉相关自注意力&#xff08;C2SAC^2SAC2SA, Query-Key&#xff09;替换为自相关自注意力&#xff08;SCSA, Query-Query或Key-Key&#xff09;来解决空间不变性问题 。然而&#xff0c;这些…

作者头像 李华