【C++习题集】-- 堆

(用于复习)

目录

树概念及结构

名词概念

二叉树概念及结构

特殊的二叉树

满二叉树

完全二叉树

运算性质

二叉树存储结构

顺序存储

链式存储

堆 - 顺序存储

堆的性质

堆的实现

堆的应用

堆排序

直接建堆法


树概念及结构

        概念非线性的数据结构(形成的倒挂似树的结构 - 根朝上,叶朝下,子树之间不能有交集)。

名词概念

  • 节点的度一个节点含有的子树的个数称为该节点的度。
  • 叶节点或终端节点:度为0的节点称为叶节点。
  • 非终端节点或分支节点:度不为0的节点。
  • 双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点。
  • 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点。
  • 兄弟节点:具有相同父节点的节点互称为兄弟节点。
  • 树的度一棵树中,最大的节点的度称为树的度。
  • 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推。
  • 树的高度或深度树中节点的最大层次。
  • 堂兄弟节点:双亲在同一层的节点互为堂兄弟。
  • 节点的祖先:从根到该节点所经分支上的所有节点。
  • 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。
  • 森林:由m(m>0)棵互不相交的树的集合称为森林。

二叉树概念及结构

        由一个根节点加上两棵别称为左子树和右子树的二叉树组成 - 子树可为空。

  • 不存在度大于2的结点。

特殊的二叉树

满二叉树

        每一个层的结点数都达到最大值,则结点总数:2^k - 1(K层数)

完全二叉树

        特殊的完全二叉树 - 最后一层不满,但是是左到右是连续的

        (满二叉树是特殊的完全二叉树)

运算性质

  • 根节点的层数为1,则第i层上最多有2^(i - 1)个结点
  • 根节点的层数为1,则深度h的最大结点数是2^h - 1
  • 根节点的层数为1,n个结点的满二叉树的深度h = log2(n + 1)
  • 如果度为0其叶结点个数为n,度为2的分支结点个数为m,则有:n = m + 1
  • n个结点的完全二叉树,以数组顺序对所有节点开始编号:
  1. 若i>0,i位置节点的双亲序号:(i - 1) / 2
  2. 若2i + 1 < n,左孩子序号:2i + 1,2i + 1 >= n否则无左孩子
  3. 若2i + 2 < n,右孩子序号:2i + 2,2i + 2 >= n否则无右孩子

一个具有767个节点的完全二叉树,其叶子节点个数为()

A、383
B、384
C、385
D、386
------------------------------------------
正确答案:B
------------------------------------------
解析:
        不要只想最后一层,倒数第二层也是会有叶子节点的。
首先以:

        可以推算出是第1 ~ 9层为满二叉树,对应节点数:511。可以知道最后一层一定为叶子节点:256个。

        然后根据完全二叉树是最后一层不满,但是是左到右是连续的,于是256 / 2 = 128,所以倒数第二层有128个是最后一层的父节点。

 再根据:

        可知倒数第二层有256个节点,于是叶子节点:256 + 256 - 128 = 384。

二叉树存储结构

顺序存储

        用数组来存储,适合表示完全二叉树。

  • 物理上:数组
  • 逻辑上:二叉树

链式存储

        链表来表示一棵二叉树。

  • 二叉链:数据域和左右指针域
  • 三叉链:数据域和左右上指针域

堆 - 顺序存储

        堆是一种特殊的完全二叉树,只不过父亲与儿子节点间有关系。顺序存储的完全二叉树典型的就是堆。(普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储)

堆的性质

  • 堆中某个节点的值总是不大于或不小于其父节点的值
    • 小堆:父亲位,比孩子位,要小
    • 大堆:父亲位,比孩子位,要大
  • 堆总是一棵完全二叉树

堆的实现

#include <iostream>
#include <cassert>namespace qcr_heap
{typedef int HeapType;struct Heap{int64_t _capacity; // 动态开辟可用大小int64_t _size;     // 实际数据占用大小HeapType *_array;  // 动态开辟一维数组};/********** 初始化堆*********/void HeapInit(Heap *heap){assert(heap);heap->_capacity = 0;heap->_size = 0;heap->_array = 0;}/********** 销毁堆*********/void HeapDestory(Heap *heap){assert(heap);heap->_capacity = 0;heap->_size = 0;free(heap->_array);heap->_array = nullptr;}/********** 小根堆*********/bool less(HeapType element_1, HeapType element_2){return element_1 < element_2;}/********** 大根堆*********/bool greater(HeapType element_1, HeapType element_2){return element_1 > element_2;}/********** 交换数据*********/void swap(HeapType *element_1, HeapType *element_2){HeapType tmp = *element_1;*element_1 = *element_2;*element_2 = tmp;}/****************************** 向上调整*   heap: 输入型参数,堆地址*   child: 输入型参数,排序的插入节点*   Func: 输入型参数,大小堆*****************************/void AdjustUp(Heap *heap, int64_t child, bool (*Func)(HeapType, HeapType)){assert(heap);int64_t parent = (child - 1) / 2;while (child > 0){if (Func(heap->_array[child], heap->_array[parent])){swap(&(heap->_array[child]), &(heap->_array[parent]));child = parent;parent = (child - 1) / 2;}elsebreak;}}/****************************** 向下调整*   heap: 输入型参数,堆地址*   root: 输入型参数,排序的根节点*   Func: 输入型参数,大小堆*****************************/void AdjustDown(Heap *heap, int64_t root, bool (*Func)(HeapType, HeapType)){assert(heap);int64_t parent = root;int64_t child = parent * 2 + 1;while (child < heap->_size){if (child + 1 < heap->_size && Func(heap->_array[child + 1], heap->_array[child])){child++;}if (Func(heap->_array[child], heap->_array[parent])){swap(&(heap->_array[child]), &(heap->_array[parent]));parent = child;child = parent * 2 + 1;}else{break; // 符合堆就成立了,就没必要进行交换了。}}}/****************************** 存入数据*   heap: 输入型参数,堆地址*   data: 输入型参数,插入的数据*   Func: 输入型参数,大小堆*****************************/void HeapPush(Heap *heap, HeapType data, bool (*Func)(HeapType, HeapType)){assert(heap);if (heap->_capacity == heap->_size){int64_t newcapacity = heap->_capacity == 0 ? 5 : heap->_capacity * 2;HeapType * tmp = (HeapType *)realloc(heap->_array, heap->_capacity*sizeof(HeapType);if (tmp == nullptr){printf("Capacuty Get Error!\n");exit(-1);}heap->_array = tmp;heap->_capacity = newcapacity;}heap->_array[heap->_size] = data;AdjustUp(heap, heap->_size, Func);(heap->_size)++;}/****************************** 按顺序全部输出*   heap: 输入型参数,堆地址*****************************/void HeapPrint(Heap *heap){assert(heap);for (uint64_t i = 0; i < heap->_size; i++){std::cout << heap->_array[i] << " ";}std::cout << '\n';}/****************************** 首元素*   heap: 输入型参数,堆地址*****************************/HeapType HeapTop(Heap *heap){assert(heap);assert(heap->_size > 0);return heap->_array[0];}/****************************** 判空*   heap: 输入型参数,堆地址*****************************/bool HeapEmpty(Heap *heap){assert(heap);return heap->_size == 0;}/****************************** 有效数据个数*   heap: 输入型参数,堆地址*****************************/int HeapSize(Heap *heap){assert(heap);return heap->_size;}/****************************** 判空*   heap: 输入型参数,堆地址*   Func: 输入型参数,大小堆*****************************/void HeapPop(Heap *heap, bool (*Func)(HeapType, HeapType)){assert(heap);assert(heap->_size > 0);heap->_array[0] = heap->_array[heap->_size - 1];(heap->_size)--;AdjustDown(heap, 0, Func);}
}
已知小根堆为8,15,10,21,34,16,12,删除关键字 8 之后需重建堆,在此过程中,关键字之间的比较次数是()
A、1
B、2
C、3
D、4
------------------------------------------
正确答案:B
------------------------------------------
解析:
        首先我们需要知道,删除对应的调整算法是向下调整,所以其实在比较中有一个很重要的一项就是左右节点的比较,于是此处本质上的比较是需要在加上一次左右节点的比较。

堆的应用

堆排序

        利用堆删除思想来进行排序。

TOP-K问题

1. 用数据集合中前K个元素来建堆

  • 前k个最大的元素,则建小堆
  • 前k个最小的元素,则建大堆
2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素
面试题 17.14. 最小K个数 - 力扣(LeetCode)

class Solution
{
public:// 向上建堆void adjustUp(vector<int> &nums, int child){int parent = (child - 1) / 2;while (child > 0){if (nums[child] > nums[parent]){swap(nums[child], nums[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}// 向下建堆void adjustDown(vector<int> &nums, int parent){int child = parent * 2 + 1;while (child < nums.size()){if (child + 1 < nums.size() && nums[child + 1] > nums[child]){child++;}if (nums[child] > nums[parent]){swap(nums[child], nums[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}// 堆排序的TOP-k问题vector<int> smallestK(vector<int> &arr, int k){vector<int> nums;nums.reserve(k);// 前K个元素来建堆for (int i = 0; i < k; i++){nums.push_back(arr[i]);adjustUp(nums, nums.size() - 1);}// 对比堆顶元素if (k != 0){for (int i = k; i < arr.size(); i++){if (arr[i] < nums[0]){nums[0] = arr[i];adjustDown(nums, 0);}}}return nums;}
};

        并不是最优的,并且还实现了两个堆算法,编码效率过低。

直接建堆法

        原本利用向上建堆的方式,是并不够完美的,建堆的时间复杂度为O(N)。

        而直接建堆法时间复杂度O(logn),其根本是利用向下建堆实现。

for (int i = (size - 1 - 1) / 2; i >= 0; i--)
{ADjustDown(nums, i);
}
class Solution
{
public:// 向下建堆void adjustDown(vector<int> &nums, int parent){int child = parent * 2 + 1;while (child < nums.size()){if (child + 1 < nums.size() && nums[child + 1] > nums[child]){child++;}if (nums[child] > nums[parent]){swap(nums[child], nums[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}// 堆排序的TOP-k问题vector<int> smallestK(vector<int> &arr, int k){vector<int> nums;nums.reserve(k);// 前K个元素来建堆for (int i = 0; i < k; i++){nums.push_back(arr[i]);}for(int i = (k - 1 - 1) / 2; i >= 0; i--){adjustDown(nums, i);}// 对比堆顶元素if (k != 0){for (int i = k; i < arr.size(); i++){if (arr[i] < nums[0]){nums[0] = arr[i];adjustDown(nums, 0);}}}return nums;}
};

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

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

相关文章

【目标检测中对IoU的改进】GIoU,DIoU,CIoU的详细介绍

文章目录 1、IoU2、GIoU(Generalized Intersection over Union)3、DIoU4、CIoU 1、IoU IoU为交并比&#xff0c;即对于pred和Ground Truth&#xff1a;交集/并集 1、IoU可以作为评价指标使用&#xff0c;也可以用于构建IoU loss 1 - IoU 缺点&#xff1a; 2、对于pred和GT相…

[MySQL]主从服务器布置

配置主服务器 配置文件 /etc/my.cnf 在[mysqld]下进行配置 log_binON //启动二进制日志 log-bin mysql-bin //启用二进制日志&#xff0c;用于记录主服务器的更新操作 server-id 1 // 用来表示mysql服务id,保证集成环境中的唯一性 , 范围 [1,2^32) read-only0 // 1表示只…

ChatGLM-6B微调记录

目录 GLM-130B和ChatGLM-6BChatGLM-6B直接部署基于PEFT的LoRA微调ChatGLM-6B GLM-130B和ChatGLM-6B 对于三类主要预训练框架&#xff1a; autoregressive&#xff08;无条件生成&#xff09;&#xff0c;GPT的训练目标是从左到右的文本生成。autoencoding&#xff08;语言理解…

如何在windows电脑安装多个tomcat服务器和乱码问题

前提条件安装jdk 以17版本为例&#xff0c;将jdk8卸载干净 1.首先进入tomcat官网下载 tomcat网址 这里下载tomcat10为例子 1.1 这里选择方式一 下载解压版 2.解压后拷贝三份 分别命名为 8081、 8082、 8083 3.分别对每个tomcat执行以下操作 3.1 找到tomcat所在webapps文…

java的类和对象详解

一、java是面向对象的编程语言 首先一般的编程语言有两种&#xff0c;一种是面向对象&#xff0c;一种是面向过程。前者更加关注代码中对象与对象之间关系与协作&#xff0c;而后者更加注重代码的执行过程。 举个例子 传统的方式&#xff1a;注重的是洗衣服的过程&#xff0c;…

引领行业高质量发展|云畅科技参编《低代码开发平台创新发展路线图(2023)》

8月8日-9日&#xff0c;中国电子技术标准化研究院于北京顺利召开《低代码开发平台创新发展路线图&#xff08;2023&#xff09;》封闭编制会。云畅科技、浪潮、百度、广域铭岛等来自低代码开发平台解决方案供应商、用户方、科研院所等近30家相关单位的40余位专家参与了现场编制…

CentOS 8.5修改安装包镜像源

1 备份原配置 cd /etc/yum.repos.d mkdir backup mv *.repo backup/2 下载镜像源 2.1 使用wget下载 wget http://mirrors.aliyun.com/repo/Centos-8.repo2.2 使用curl下载 我是安装的最小版本的系统&#xff0c;默认只有curl curl使用方法&#xff1a;https://www.ruanyife…

【分布式共识】Multi-Paxos 算法思想

上一篇文章主要聊了Basic Paxos算法&#xff0c;而Multi-Paxos并不是一种算法&#xff0c;是一种算法思想。具体就是Basic Paxos解决的是对一个值达成共识。而后者是通过执行多次的Basic Paxos算法就多个值达成一致。具体的落地实现有Raft。 Muti-Paxos的问题 在Basic Paxos中…

14、缓存预热+缓存雪崩+缓存击穿+缓存穿透

缓存预热缓存雪崩缓存击穿缓存穿透 ● 缓存预热、雪崩、穿透、击穿分别是什么&#xff1f;你遇到过那几个情况&#xff1f; ● 缓存预热你是怎么做到的&#xff1f; ● 如何避免或者减少缓存雪崩&#xff1f; ● 穿透和击穿有什么区别&#xff1f;它两一个意思还是截然不同&am…

CW4-6A-S、CW4-10A-S、CW4-20A-S、CW4-30A-S螺栓式滤波器

CW3L2-3A-S、CW3L2-6A-S、CW3L2-10A-S、CW3L2-20A-S CW3-3A-S、CW3-6A-S、CW3-10A-S、CW3-20A-S、CW3-30A-S CW4EL2-3A-S、CW4EL2-6A-S、CW4EL2-10A-SCW4EL2-20A-S、CW4EL2-30A-S CW4E-3A-S、CW4E-6A-S、CW4E-10A-S、CW4E-20A-S、CW4E-30A-S CW4E-40A-S(001)、CW4E-50A-S(0…

论文导读 | Operation ResearchManagement Science近期文章精选

推文作者&#xff1a;周梓渊 编者按 如何准确估计和预测债券风险溢价&#xff1f;债券保险是否为市政债券的发行人提供价值&#xff1f;我们如何界定社会福利政策对小部分群体的负面影响&#xff1f;垄断零售商的线上线下定价有何诀窍&#xff1f;顶刊中的行为理论真的对应现实…

排名前 6 位的数学编程语言

0 说明 任何对数学感兴趣或计划学习数学的人&#xff0c;都应该至少对编程语言有一定的流利程度。您不仅会更有就业能力&#xff0c;还可以更深入地理解和探索数学。那么你应该学习什么语言呢&#xff1f; 1.python 对于任何正在学习数学的人来说&#xff0c;Python都是一门很棒…

win10系统docker创建ubuntu容器解决开发环境问题

一、win10系统使用docker的原因 最近啊&#xff0c;在学习人工智能-深度学习&#xff0c;用的win10系统进行开发&#xff0c;老是出现一些莫名其妙的问题&#xff0c;无法解决&#xff0c;每天都在为环境问题搞得伤透了脑筋。 说到底还是要使用Linux系统进行开发比较合适。 …

跟随角色镜头时,解决地图黑线/白线缝隙的三种方案

下面一共三个解决方案&#xff0c;这里我推荐第二个方案解决&#xff0c;因为够快速和简单。 现象&#xff1a; 解决方案一&#xff1a; 参考【Unity2D】去除地图中的黑线_unity选中后有线_香菇CST的博客-CSDN博客&#xff0c;博主解释是因为抗锯齿采样导致的问题。 具体到这…

【后端】Core框架版本和发布时间以及.net 6.0启动文件的结构

2023年&#xff0c;第35周&#xff0c;第1篇文章。给自己一个目标&#xff0c;然后坚持总会有收货&#xff0c;不信你试试&#xff01; .NET Core 是一个跨平台的开源框架&#xff0c;用于构建现代化的应用程序。它在不同版本中有一些重要的区别和发布时间 目录 一、Core版本和…

【OpenVINOSharp】在英特尔® 开发者套件爱克斯开发板使用OpenVinoSharp部署Yolov8模型

在英特尔 开发者套件爱克斯开发板使用OpenVinoSharp部署Yolov8模型 一、英特尔开发套件 AIxBoard 介绍1. 产品定位2. 产品参数3. AI推理单元 二、配置 .NET 环境1. 添加 Microsoft 包存储库2. 安装 SDK3. 测试安装4. 测试控制台项目 三、安装 OpenVINO Runtime1. 下载 OpenVINO…

Linux的热拔插UDEV机制

文章目录 UDEV简介守护进程基本特点 守护进程和后台进程的区别开发守护进程结束 UDEV简介 udev是一个设备管理工具&#xff0c;udev以守护进程的形式运行&#xff0c;通过侦听内核发出来的uevent来管理/dev目录下的设备文件。 udev在用户空间运行&#xff0c;而不在内核空间 …

css 文字排版-平铺

序&#xff1a; 1、表格的宽度要有&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 2、容器不能是display:inline 3、扩展---》node全栈框架 代码 text-align-last: justify; width: 70px; display: inline-block; 主要是用于表单左侧文字排序&#xff01;

resource doesn‘t have a corresponding Go package.

resource doesnt have a corresponding Go package. GO这个鬼东西不能直接放src下。 ************ Building Go project: ProjectGoTest ************with GOPATH: D:\Go;D:\eclipse-jee-oxygen-2-win32-x86_64\workspace\ProjectGoTest >> Running: D:\Go\bin\go.exe …

探索人工智能 | 模型训练 使用算法和数据对机器学习模型进行参数调整和优化

前言 模型训练是指使用算法和数据对机器学习模型进行参数调整和优化的过程。模型训练一般包含以下步骤&#xff1a;数据收集、数据预处理、模型选择、模型训练、模型评估、超参数调优、模型部署、持续优化。 文章目录 前言数据收集数据预处理模型选择模型训练模型评估超参数调…