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,一经查实,立即删除!

相关文章

LLM系列(2):开源LLM Promp调优之道进阶指南

LLM系列(2):开源LLM Promp调优之道进阶指南 随着大模型在不同领域场景的应用,AI 技术的落地方式也有了很大的颠覆,基于大模型的 AI 技术方案重构已成为当前热点和未来趋势。但另一方面,面向不同领域场景构建行业专属大模型,对底层计算资源要求比较高,通常需要大量的 GPU…

升级cmake

要升级CMake&#xff0c;您可以按照以下步骤进行操作&#xff1a; 下载最新版本&#xff1a;首先&#xff0c;您需要从CMake官方网站下载最新版本的CMake。他们提供了适用于各种操作系统的安装程序。 卸载旧版本&#xff08;可选&#xff09;&#xff1a;在安装新版本之前&…

使用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 对象…

GO语言核心30讲 进阶技术 (第二部分)

原站地址&#xff1a;Go语言核心36讲_Golang_Go语言-极客时间 一、接口类型的合理运用 1. 接口类型只包含方法&#xff0c;不包含字段。 方法集合就是它的全部特征。 任何数据类型&#xff0c;只要实现了接口的方法集合全部&#xff0c;那么它就是这个接口的实现类型 2. 怎么…

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

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

【java9】java9新特性之模块化

Java9模块化是Java9版本中引入的一个重要特性&#xff0c;通过Java Platform Module System (JPMS)实现。这个特性允许开发者将大型应用程序拆分成相互独立的模块&#xff0c;每个模块包含一组相关的功能和资源。 关键概念与语法 下面是Java9模块化的一些关键概念和语法&…

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

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

selenium之document.querySelector()方法

document.querySelector()方法 1. 常用的三种获取元素的js方式 document.getElementById("");document.getElementsByClassName();document.getElementsByTagName(); var docdocument;var boxdoc.getElementById("box");var libox.getElementsByTagName(…

Ceph PG

概述 为了实现不同存储池之间的策略隔离&#xff0c;以及针对不同用途的存储池指定不同的容灾策略&#xff0c;ceph crush使用中间结构即Placement Group&#xff08;后续均以PG简称&#xff09;将应用数据对象进行映射后&#xff0c;写入OSD本地存储设备。PG也是我们日常运维…

常见的 HTML 标准

常见的 HTML 标准 常见的 HTML 标准发布历史 HTML&#xff08;Hypertext Markup Language&#xff09;有多个版本和标准。以下是一些常见的 HTML 标准&#xff1a; HTML 2.0&#xff1a;于1995年发布&#xff0c;是 HTML 的第一个正式标准。HTML 3.2&#xff1a;于1997年发布…

刷代码随想录有感(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 &&…

python挑战10秒小程序

目录 一.前言 二.代码 三.分析 一.前言 >1.小程序开始时,会出现一个倒计时器,从10秒开始。 >2.玩家需要集中注意力并估计10秒钟过去的时间。 >3.当玩家认为10秒钟已经过去时,需要点击屏幕上的按钮。 >4.小程序会显示玩家的点击时间,以及与实际10秒钟的时间…

wetrtc简介

WebRTC&#xff08;Web Real-Time Communication&#xff09;是一种实时通信技术&#xff0c;它允许网络应用或站点在无需中间媒介的情况下&#xff0c;直接在浏览器之间建立点对点&#xff08;Peer-to-Peer&#xff09;的连接&#xff0c;实现音频、视频流或其他任意数据的实时…

泰勒创造力达到顶峰?(上)

hello,大家好&#xff01;今天看一篇经济学人的一篇评论&#xff0c;说的是泰勒斯威夫特当前的创造力。经济学人总是语不惊人死不休&#xff0c;看看它对这位音乐天才做了怎样的评价。 事先声明哈&#xff0c;本文就是一种英语学习类讲述&#xff0c;没带任何个人色彩&#xff…

网络舆情分析:利用自然语言处理(NLP)洞察公众情绪

&#x1f310; 网络舆情分析&#xff1a;利用自然语言处理&#xff08;NLP&#xff09;洞察公众情绪 &#x1f4ca; 概述 在数字化时代&#xff0c;公众情绪和舆论对企业品牌、政治决策乃至社会趋势都有着深远的影响。通过自然语言处理&#xff08;NLP&#xff09;技术&#…

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

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

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

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