C++ 堆结构和堆排序(从顶到底/从底到顶的大顶堆)+ 优化

一、堆结构和堆排序 

(1)heapInsert,向上调整大根堆 和 heapify,向下调整大根堆

// i位置的数,向上调整大根堆
// arr[i] = x,x是新来的!往上看,直到不比父亲大,或者来到0位置(顶)
void heapInsert(vector<int>& arr, int i) {// i -> 父: (i - 1) / 2while (arr[i] > arr[(i - 1) / 2]) {swap(arr, i, (i - 1) / 2);i = (i - 1) / 2;}
}
// i位置的数,变小了,又想维持大根堆结构
// 向下调整大根堆
// 当前堆的大小为size
void heapify(vector<int>& arr, int i, int size) {int l = i * 2 + 1;while (l < size) {// 有左孩子,l// 右孩子,l+1// 评选,最强的孩子,是哪个下标的孩子int best = l + 1 < size && arr[l + 1] > arr[l] ? l + 1 : l;// 上面已经评选了最强的孩子,接下来,当前的数和最强的孩子之前,最强下标是谁best = arr[best] > arr[i] ? best : i;// 如果最强的下标,是当前的数,那么当前的数已经满足大根堆结构,退出if (best == i) { // 最强的是自己break;}swap(arr, best, i);i = best;l = i * 2 + 1;}
}

 二、从顶到底建立大根堆 

 

完整代码:

#include <iostream>
using namespace std;
#include <vector>// 堆结构和堆排序,填函数练习风格
// 测试链接 : https://leetcode.cn/problems/sort-an-array/class heapSort {
public:vector<int> sortArray(vector<int> arr) {if (arr.size() > 1) {// heapSort1 为从顶到底建堆然后排序// heapSort2 为从底到顶建堆然后排序// 用哪个都可以heapSort1(arr);//heapSort2(arr);}return arr;}// i位置的数,向上调整大根堆// arr[i] = x,x是新来的!往上看,直到不比父亲大,或者来到0位置(顶)void heapInsert(vector<int>& arr, int i) {// i -> 父: (i - 1) / 2while (arr[i] > arr[(i - 1) / 2]) {swap(arr, i, (i - 1) / 2);i = (i - 1) / 2;}}// i位置的数,变小了,又想维持大根堆结构// 向下调整大根堆// 当前堆的大小为sizevoid heapify(vector<int>& arr, int i, int size) {int l = i * 2 + 1;while (l < size) {// 有左孩子,l// 右孩子,l+1// 评选,最强的孩子,是哪个下标的孩子int best = l + 1 < size && arr[l + 1] > arr[l] ? l + 1 : l;// 上面已经评选了最强的孩子,接下来,当前的数和最强的孩子之前,最强下标是谁best = arr[best] > arr[i] ? best : i;// 如果最强的下标,是当前的数,那么当前的数已经满足大根堆结构,退出if (best == i) { // 最强的是自己break;}swap(arr, best, i);i = best;l = i * 2 + 1;}}void swap(vector<int>& arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}// 从顶到底建立大根堆,O(n * logn)// 依次弹出堆内最大值并排好序,O(n * logn)// 整体时间复杂度O(n * logn)void heapSort1(vector<int>& arr) {int n = arr.size();for (int i = 0; i < n; i++) {heapInsert(arr, i);}int size = n;while (size > 1) {swap(arr, 0, --size);heapify(arr, 0, size);}}
};int main() {//vector<int> arr = { 10,0,20,5,89,70,65,45 };//vector<int> arr = { 20,30,15,10,9,8,12,45,0,23 };vector<int> arr = { 5,6,3,1,9,2,4,6 };heapSort hs;vector<int> res = hs.sortArray(arr);for (int i = 0; i < res.size(); i++) {cout << res[i] << " ";}cout << endl;return 0;
}

三、从底到顶建立大根堆  

依次弹出堆内最大值并排好序

完整代码:

#include <iostream>
using namespace std;
#include <vector>// 堆结构和堆排序,填函数练习风格
// 测试链接 : https://leetcode.cn/problems/sort-an-array/class heapSort {
public:vector<int> sortArray(vector<int> arr) {if (arr.size() > 1) {// heapSort1 为从顶到底建堆然后排序// heapSort2 为从底到顶建堆然后排序// 用哪个都可以//heapSort1(arr);heapSort2(arr);}return arr;}// i位置的数,向上调整大根堆// arr[i] = x,x是新来的!往上看,直到不比父亲大,或者来到0位置(顶)void heapInsert(vector<int>& arr, int i) {// i -> 父: (i - 1) / 2while (arr[i] > arr[(i - 1) / 2]) {swap(arr, i, (i - 1) / 2);i = (i - 1) / 2;}}// i位置的数,变小了,又想维持大根堆结构// 向下调整大根堆// 当前堆的大小为sizevoid heapify(vector<int>& arr, int i, int size) {int l = i * 2 + 1;while (l < size) {// 有左孩子,l// 右孩子,l+1// 评选,最强的孩子,是哪个下标的孩子int best = l + 1 < size && arr[l + 1] > arr[l] ? l + 1 : l;// 上面已经评选了最强的孩子,接下来,当前的数和最强的孩子之前,最强下标是谁best = arr[best] > arr[i] ? best : i;// 如果最强的下标,是当前的数,那么当前的数已经满足大根堆结构,退出if (best == i) { // 最强的是自己break;}swap(arr, best, i);i = best;l = i * 2 + 1;}}void swap(vector<int>& arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}// 从底到顶建立大根堆,O(n)// 依次弹出堆内最大值并排好序,O(n * logn)// 整体时间复杂度O(n * logn)void heapSort2(vector<int>& arr) {int n = arr.size();for (int i = n - 1; i >= 0; i--) {heapify(arr, i, n);}int size = n;while (size > 1) {swap(arr, 0, --size);heapify(arr, 0, size);}}
};int main() {//vector<int> arr = { 10,0,20,5,89,70,65,45 };//vector<int> arr = { 20,30,15,10,9,8,12,45,0,23 };vector<int> arr = { 5,6,3,1,9,2,4,6 };heapSort hs;vector<int> res = hs.sortArray(arr);for (int i = 0; i < res.size(); i++) {cout << res[i] << " ";}cout << endl;return 0;
}

四、计算复杂度 

总结堆结构

  1. 完全二叉树和数组前缀范围的对应
  2. i的父亲节点:(i-1)/2,i的左孩子:i*2+1,i的左孩子:i*2+2
  3. 堆的定义(大根堆,小根堆),本节课讲解按照大根堆来讲解,小根堆是同理的
  4. 堆的调整:heapInsert(向上调整),heapify(向下调整)
  5. heapInsert、heapify方法的单次调用,时间复杂度O(logn),完全二叉树的结构决定的

堆排序

  • A.从顶到底建堆,时间复杂度O(n*logn),log1 + log2 + log3 + ... + logn -> O(n*logn)
  • B.从底到顶建堆,时间复杂度O(n),总代价就是简单的等比数列关系,为啥会有差异?简单图解一下
  • C.建好堆之后的调整阶段,从最大值到最小值依次归位,时间复杂度O(n*logn),不管以什么方式建堆,调整阶段的时间复杂度都是这个 ,所以整体复杂度也是这个额外空间复杂度是O(1),因为堆直接建立在了要排序的数组上,所以没有什么额外空间

注意:堆结构比堆排序有用的多,尤其是和比较器结合之后,后面博客会重点讲述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/5393.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Gradio搭建聊天UI实现质谱AI智能问答

一、调用智谱 AI API 1、获取api_key 智谱AI开放平台网址&#xff1a; https://open.bigmodel.cn/overview 2、安装库pip install zhipuai 3、执行一下代码&#xff0c;调用质谱api进行问答 from zhipuai import ZhipuAIclient ZhipuAI(api_key"xxxxx") # 填写…

短视频交友系统搭建重点,会用到哪些三方服务?

在搭建短视频交友系统时&#xff0c;为了确保系统的稳定性、安全性和用户体验&#xff0c;通常需要用到多种第三方服务。以下是搭建短视频交友系统时可能用到的关键第三方服务&#xff1a; 云服务提供商&#xff1a;如阿里云、腾讯云等&#xff0c;提供稳定、可扩展的服务器资源…

如何消除SmartScreen“未知发布者”警告?

在互联网高速发展、应用程序遍地开花的当今时代&#xff0c;作为企业&#xff0c;我们通常会开发自己的应用程序来开展自己的业务&#xff0c;以便与客户建立更深入的联系。不少应用程序所有者可能会面临一个难题&#xff0c;那就是用户下载时&#xff0c;系统会弹出SmartScree…

nuxt3项目服务端bulid后在本地浏览的3种方式(nuxi preview、Node.js Server、PM2)

你也许会问有了开发调试本地浏览&#xff0c;为什么还要服务端构建之后在本地浏览&#xff1f; 举个简单例子 在 Nuxt 3 服务端打包中&#xff0c;由于运行环境不同&#xff0c;无法直接访问 process 对象。服务端打包通常是在 Node.js 环境中进行的&#xff0c;而 process 对象…

设计模式之代理模式ProxyPattern(六)

一、代理模式介绍 1、什么是代理模式&#xff1f; 代理模式是一种结构型设计模式&#xff0c;它允许为其他对象提供一个替代品或占位符&#xff0c;以控制对这个对象的访问。 2、代理模式的角色构成 抽象主题&#xff08;Subject&#xff09;&#xff1a;定义了真实主题和代…

记一次使用Notepad++正则表达式批量替换SQL语句

目录 一、需求二、解决方案三、正则解析 一、需求 存在如下SQL建表脚本&#xff1a; CREATE TABLE "BUSINESS_GOODS" ( "ID" VARCHAR(32) NOT NULL, "GOODS_CODE" VARCHAR(50), "GOODS_NAME" VARCHAR(100), ... NOT CLUSTER PRIMARY…

刷代码随想录有感(50):路径总和

题干&#xff1a; 代码; class Solution { public:bool traversal(TreeNode* node, int count){if(node NULL)return false;if(!node -> left && !node -> right && count 0)return true;if(!node -> left && !node -> right &&…

北京金融大数据有限公司X百望云签署战略合作协议 共同发布“金数数据要素流通云平台”

随着数据资产与数据要素相关政策密集出台&#xff0c;资本与实业企业均跃跃欲试。但因为没有龙头企业的方案引领和成熟的落地实践&#xff0c;市场呈谨慎观望态势&#xff0c;热度无处安放。 北京金融大数据有限公司&#xff08;以下简称“金融大数据公司”&#xff09;作为市…

动手学深度学习——softmax分类

1. 分类问题 回归与分类的区别&#xff1a; 回归可以用于预测多少的问题&#xff0c; 比如"预测房屋被售出价格"&#xff0c;它是个单值输出。softmax可以用来预测分类问题&#xff0c;例如"某个图片中是猫、鸡还是狗&#xff1f;"&#xff0c;这是一个多…

深入理解正则表达式:从入门到精通

title: 深入理解正则表达式&#xff1a;从入门到精通 date: 2024/4/30 18:37:21 updated: 2024/4/30 18:37:21 tags: 正则Python文本分析日志挖掘数据清洗模式匹配工具推荐 第一章&#xff1a;正则表达式入门 介绍正则表达式的基本概念和语法 正则表达式是一种用于描述字符串…

Bert基础(二十一)--Bert实战:文本摘要

一、介绍 1.1 文本摘要简介 文本摘要&#xff08;Text Summarization&#xff09;&#xff0c;作为自然语言处理&#xff08;NLP&#xff09;领域的一个分支&#xff0c;其核心目标是从长篇文档中提取关键信息&#xff0c;并生成简短的摘要&#xff0c;以提供对原始内容的高度…

Go语言map

map 概念 在Go语言中&#xff0c;map 是一种内建的数据结构&#xff0c;它提供了一种关联式的存储机制&#xff0c;允许你以键值对的形式存储数据。每个键都是唯一的&#xff0c;并且与一个值相关联。你可以通过键来查找、添加、更新和删除值&#xff0c;这类似于其他编程语言…

Android 音视频播放器 Demo(二)—— 音频解码与音视频同步

音视频编解码系列目录&#xff1a; Android 音视频基础知识 Android 音视频播放器 Demo&#xff08;一&#xff09;—— 视频解码与渲染 Android 音视频播放器 Demo&#xff08;二&#xff09;—— 音频解码与音视频同步 RTMP 直播推流 Demo&#xff08;一&#xff09;—— 项目…

Qt+Ubuntu20.04:打包qt

打包程序 参考 qt项目在Linux平台上面发布成可执行程序.run_qt.run不是虚拟机的配置文件-CSDN博客 Linux下Qt程序的打包发布(1)-不使用第三方工具 - 知乎 (zhihu.com) 过程 1、Release编译 先将你的程序在release下编译通过&#xff0c;保证下面打包的程序是你最新的。 2…

C#调用skiasharp操作并绘制图片

之前学习ViewFaceCore时采用Panel控件和GDI将图片及识别出的人脸方框和关键点绘制出来&#xff0c;本文将其修改为基于SKControl和SKCanvas实现相同的显示效果并支持保存为本地图片。   新建Winform项目&#xff0c;在Nuget包管理器中搜索并安装一下SkiaSharp和ViewFaceCore…

HTTP 多个版本

了解一下各个版本的HTTP。 上个世纪90年代初期&#xff0c;蒂姆伯纳斯-李&#xff08;Tim Berners-Lee&#xff09;及其 CERN的团队共同努力&#xff0c;制定了互联网的基础&#xff0c;定义了互联网的四个构建模块&#xff1a; 超文本文档格式&#xff08;HTML&#xff09; …

Linux基础——Linux开发工具(上)_vim

前言&#xff1a;在了解完Linux基本指令和Linux权限后&#xff0c;我们有了足够了能力来学习后面的内容&#xff0c;但是在真正进入Linux之前&#xff0c;我们还得要学会使用Linux中的几个开发工具。而我们主要介绍的是以下几个&#xff1a; yum, vim, gcc / g, gdb, make / ma…

【初识Redis】

初识Redis Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的内存数据库&#xff0c;它提供了一个高性能的键值存储系统&#xff0c;并且支持多种数据结构&#xff0c;包括字符串、哈希、列表、集合和有序集合等。Redis的特点包括&#xff1a; 内存存储&…

C语言实验-数组、字符串以及指针

一&#xff1a; 求一个NN矩阵主、次对角线上所有元素之和。矩阵输入、矩阵输出、矩阵对角线求和分别用三个子函数实现。&#xff08;N的值由用户从键盘输入&#xff09; #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h>void print(int(*arr…

有哪些好用的局域网电脑监控系统软件?

企业员工不好管理&#xff1f;&#xff1f;&#xff1f; 局域网已成为企业日常运营不可或缺的一部分。 然而&#xff0c;随着网络技术的普及&#xff0c;员工在局域网中的不当行为也日益增多&#xff0c;如滥用网络资源、泄露敏感信息、消极怠工等。 为了解决这些问题&#x…