数据结构初阶 —— 树(堆)

2023-05-16

目录

一,堆

堆的概念

向下调整法(数组)

向上调整法(数组)

堆的创建(建堆)

堆的实现 


一,堆

堆的概念

  • 如有个关键码的集合K={k_{0}k_{1}k_{2},...,k_{n-1}},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足 k_{i}<=k_{2*i+1} 且 k_{i}<=k_{2*i+2} (k_{i}>=k_{2*i+1} 且 k_{i}>=k_{2*i+2}),i=0、1、...,则称为小堆(大堆);

小堆

  • k_{i}<=k_{2*i+1} 且 k_{i}<=k_{2*i+2} ,即所有节点小于等于孩子;
  • 根节点最小,叫做最小堆或小根堆;

大堆

  • k_{i}>=k_{2*i+1} 且 k_{i}>=k_{2*i+2} ,即所有节点大于等于孩子;
  • 根节点最大,叫做最大堆或大根堆;

堆的性质

  • 堆中某个节点的值,总是不大于或不小于其父节点的值;
  • 根一定是最值(最大值或最小值);
  • 堆总是一颗完全二叉树,适合顺序结构存储;

向下调整法(数组)

  • 将数组看做为一颗完全二叉树,可使用向下调整法创建堆;
  • 前提条件为,此二叉树的左右子树需是一个堆,只有根节点不满足堆要求;
  • 从根开始,与左右子节点中的最小值,比较并交换,依次类推,直到比父亲大或到叶子节点终止;
  • 时间复杂度,O(logN);
  • 注,向上调整法类似;
int array[] = {27,15,19,18,28,34,65,49,25,37};

//向下调整法,小堆
void Swap(int* px, int* py)
{
	int tmp = *px;
	*px = *py;
	*py = tmp;
}

void AdjustDown(int* arr, int n, int parent)
{
	int child = 2 * parent + 1;

	//无孩子节点或父亲小于孩子,即终止
	while (child < n)
	{
		if (child + 1 < n && arr[child + 1] < arr[child])
			child++;
		
		if (arr[parent] > arr[child])
		{
			Swap(arr + parent, arr + child);
			parent = child;
			child = 2 * parent + 1;
		}
		else
			break;
	}
}

向上调整法(数组)

//向上调整法
void AdjustUp(int* arr, int child)
{
	int parent = (child - 1) / 2;

	//大堆
	//根节点或父亲大于孩子,即终止
	while (child > 0)
	{
		if (arr[parent] < arr[child])
		{
			Swap(arr + parent, arr + child);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
			break;
	}
}

堆的创建(建堆)

  •  即对数据如数组(可看为完全二叉树),将其构建为堆;
  • 方法为,从倒数第一个非叶子节点的子树开始调整,直到根节点为止;
  • 即每次调整时,使用向下调整法;
  • 建堆时间复杂度,O(N),下面有证明;
  • 注,也可使用向上调整法建堆,但初始化堆的个别元素位置可能不一样;
int arr[] = {1,5,3,8,7,6}; 
//建堆-向下调整法
void Heap(int* arr, int n)
{
	int i = (n - 1 - 1) / 2; //最后节点的父节点
	for (i; i >= 0; i--)
	{
		AdjustDown(arr, n, i);
	}
}
//建堆-向上调整法
void Heap(int* arr, int n)
{
	int i = 1; 
	for (i; i < n; i++)
	{
		AdjustUp(arr, i);
	}
}

建堆时间复杂度

堆排序  

  • 升序,建大堆(将最大的数换到最后,在将剩下的数向下调整下,选出次大数,依次类推);
  • 降序,建小堆(将最小的数换到最后,在将剩下的数向下调整下,选出次小数,依次类推);
  • 整体的时间复杂度,O(N*logN);
  • 如升序建小堆(或降序建大堆)的话,选出最值后,需在继续建堆(O(N)),效率较低,还不如直接遍历,建堆的价值未体现;
//建堆排序
void HeapSort(int* arr, int n)
{
	//建堆 - O(N)
	int i = (n - 1 - 1) / 2; //最后节点的父节点
	for (i; i >= 0; i--)
	{
		AdjustDown(arr, n, i);
	}

	//排序 - O(N*log(N))
	int end = n - 1;
	while (end)
	{
		Swap(arr, arr + end);
		AdjustDown(arr, end, 0);
		end--;
	}
}

堆的实现 

//堆
typedef int HPDataType;

typedef struct Heap
{
	HPDataType* data;
	int size;
	int capacity;
}Heap;

//初始化
void HeapInit(Heap* php, HPDataType* arr, int n);

//释放销毁
void HeapDestroy(Heap* php);

//插入数据并保持堆
void HeapPush(Heap* php, HPDataType* x);

//删除堆顶数据并保持堆
void HeapPop(Heap* php);

//返回堆顶数据
HPDataType HeapTOP(Heap* php);

//返回堆节点个数
int HeapSize(Heap* php);

//判断释放为空
bool HeapEmpty(Heap* php);

注:完整接口实现代码路径https://gitee.com/napoleoncode/start-code/tree/master/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/06_Heap

TOP-K问题

  • 直接排序,O(N*log(N));
  • 建个N个数的堆,并取出前K个数,O(N+K*log(N));
  • 建个K个数的小堆,然后将剩下的数依次与堆顶比较,大即入堆,最后此堆即为最大的K个数,O(N*log(K));(如N非常大内存不够,前两种方法即适用了);
  • 注,通常K远小于N;
//TOP-K
void TOPK(int* arr, int n, int k)
{
	Heap hp;
	//建堆
	HeapInit(&hp, arr, k);

	int i = k;
	for (i; i < n; i++)
	{
		//替换
		if (HeapTop(&hp) > arr[i])
		{
			HeapPop(&hp);
			HeapPush(&hp, arr[i]);
		}
	}

	HeapPrint(&hp);
	HeapDestroy(&hp);
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构初阶 —— 树(堆) 的相关文章

  • Python pip 包的安装和卸载 使用。

    Python pip 包的安装和卸载 使用 xff08 一 xff09 pip 安装 一般 来说 Python 需要什么包 直接 pip install 包 即可 但是 这种方法太慢 因为他通过美国的服务器下载 提高 pip 速度 这里提供
  • jdk1.8安装和环境变量配置

    一 安装JDK 选择安装目录 安装过程中会出现两次 安装提示 第一次是安装 jdk xff0c 第二次是安装 jre 建议两个都安装在同一个java文件夹中的不同文件夹中 xff08 不能都安装在java文件夹的根目录下 xff0c jdk
  • python 读取PDF(tabula和pdfminer和pdfplumber的简单操作)

    一 pdfminer 读取PDF 官方文档 xff1a http www unixuser org euske python pdfminer 这里针对python3 1 模块安装 xff1a pip install i https pyp
  • 一区即将要洗的DVD片子

    101 Dalmatians Animated 2009 SE 101斑点狗 预计2009年发行特别版 12 Monkeys 05 10 2005 COM DOC 12只猴子 预计2005年5月10日发行扩展版 加评论和记录片等 2001
  • UML — 五大关系

    在UML教学视频中 xff0c 关系有四种 xff0c 而课本中有五种 xff0c 其实就是多加了一种 xff0c 那么下面我一并总结出来 1 关联关系 通俗点说就是关联关系就是两个对象他们之间的联系和关系 关联分两种 xff1a xff0
  • rhel6.5救援模式修复系统

    如果系统中很多重要的部分被删除了例如 boot下的所有东西 xff0c 则可以通过救援模式 root 64 dazzle1 桌面 mkdir backup root 64 dazzle1 桌面 cp etc fstab backup fst
  • 利用nvm安装npm失败的解决办法

    最近发现在安装nodejs后 xff0c 想使用npm发现自己的电脑上没有安装npm xff0c 可是网上都说安装了nodejs后会自动安装npm xff0c 找了很久解决办法发现没有合适的解决办法 xff0c 于是自己尝试了很久发现了问题
  • chrome 浏览器的缩略图怎么没有了?就是浏览过网页的缩略图,一点击就能打开网站。

    这个问题 xff0c 突然今天解决了 哈哈 分享 首先新标签页 点击左下角 最常访问的网站 点击 最常访问的网站 紧接着再点击被置顶端的 最常访问的网站 Ok xff0c 大功告成了 烦恼了几天的这个小功能 xff0c 有缩略图还是看着舒服

随机推荐

  • 史上最详细的PID教程——理解PID原理及优化算法

    Matlab动态PID仿真及PID知识梳理 云社区 华为云 huaweicloud com 位置式PID与增量式PID区别浅析 Z小旋 CSDN博客 增量式pid https zhuanlan zhihu com p 38337248 期望
  • ubuntu 20.04搭建samba文件共享服务器,实现基于Linux和Windows的共享文件服务

    ubuntu 20 04搭建samba文件共享服务器 xff0c 实现基于Linux和Windows的共享文件服务 超详细 一 xff0c samba的基本概念二 xff0c samba的安装三 xff0c samba的基本配置创建文件夹更
  • ERROR: Could not find a version that satisfies the requirement torchvision

    打docker时出错 xff0c ERROR Could not find a version that satisfies the requirement torchvision from versions 0 1 6 0 1 7 0 1
  • openstack 常用命令回顾及总结

    1 概述 命令实际执行基于OpenStack Queens版本 xff0c 更高版本亦可 xff0c 长时间未使用openstack有些遗忘 xff0c 整理后方便自己回顾学习 xff0c 仅供各位参考 xff0c 详细命令及参数可以参考o
  • TPMS方案 传感器 infineon篇 (SP35 SP37)

    TPMS方案 xff08 SP35 SP37 xff09 传感器 infineon篇 关于sp37无压力芯片目前已有方案 关于sp35传感器已经稳定出货 xff0c 欢迎咨询 硬件原理图 软件说明 xff1a 协议 调制方式 FSK 频率
  • sudo rosdep init 出现 ERROR: cannot download default sources list from:

    sudo rosdep init 出现 ERROR cannot download default sources list from 针对目前安装ROS出现一下指令的错误 span class token function sudo sp
  • 新装linux主机可以ping通,但是SSH无法登陆

    0 xff0c 新装一台linux主机 xff0c 可是ssh连接不上 xff0c 能ping通 怎么办呢 xff1f 1 xff0c 先查看一下防火墙状态 sudo ufw status 2 xff0c 关闭防火墙 sudo ufw di
  • tcp头以及ip头

    转自http www cnblogs com zzq919101 p 7866550 html 在网上找了很多有关tcp ip头部解析的资料 xff0c 都是类似于下面的结构 抽象出图文是这种结构 xff0c 但是在底层中数据到底是怎么传输
  • C++初阶 —— 入门/概念

    目录 一 xff0c 关键字 xff08 C 43 43 98 xff09 二 xff0c 命名空间 命名空间定义 命名空间使用 三 xff0c C 43 43 输入 输出 四 xff0c 缺省参数 五 xff0c 函数重载 六 xff0c
  • C++初阶 —— list类

    目录 一 xff0c list介绍 二 xff0c list的使用 构造函数 list iterator的使用 list capacity list element access list modifiers list迭代器失效 三 xff
  • C++初阶 —— stack/queue

    目录 一 xff0c 容器适配器 deque双端队列 二 xff0c stack栈 stack接口 stack模拟实现 三 xff0c queue队列 queue接口 queue模拟实现 四 xff0c priority queue优先级队
  • C++初阶 —— 模板进阶

    目录 一 xff0c 非类型模板参数 模板参数分类 二 xff0c 模板特化 函数模板特化 类模板特化 三 xff0c 模板分离编译 分离编译 链接失败原因 解决方法 附 模板优点 模板缺点 一 xff0c 非类型模板参数 模板参数分类 类
  • C++进阶 —— 哈希

    目录 一 xff0c 哈希的介绍 哈希的概念 哈希冲突 哈希函数 二 xff0c 哈希冲突解决 闭散列 开散列 开散列与闭散列比较 在C 43 43 98中 xff0c STL提供了底层为红黑树结构的一系列关联式容器 xff0c 查询效率可
  • Linux —— 基本指令

    目录 ls pwd cd touch mkdir rmdir rm man cp mv cat more less head tail grep date cal find zip unzip tar bc uname shutdown 附
  • Linux —— 目录结构

    转载与 xff1a Linux 系统目录结构 菜鸟教程 文件目录结构由 34 34 起始的树形结构 xff01 FHS xff08 filesystem hierarchy standard xff09 xff0c 文件系统层次化标准 xf
  • Linux —— 编译器gcc/g++

    目录 程序编译过程 gcc选项 函数库 GCC GNU Compiler Collection GUN 编译器集合 xff0c 它可以编译C C 43 43 JAV Fortran Pascal Object C Ada等语言 gcc是GC
  • 完全自学C(干货) —— 预处理详解

    目录 一 xff0c 预定义符号 二 xff0c define define定义的标识符 define定义宏 和 带副作用的宏参数 宏和函数的对比 undef 三 xff0c 命令行定义 四 xff0c 条件编译 五 xff0c 文件包含
  • 数据结构初阶 —— 树(二叉树)

    目录 一 xff0c 二叉树 特殊二叉树 二叉树的性质 二叉树的存储结构 二 xff0c 二叉树链式结构 二叉树的遍历 xff08 四种 xff09 二叉树接口 试题 一 xff0c 二叉树 由一个根节点 xff0c 加上两颗左二叉树和右二
  • rhel6和7中的服务启动以及计划任务

    rhel6下 服务启动命令 service servername start stop restart status 启动服务 xff0c 停止服务 xff0c 重启服务 xff0c 查看服务状态 etc init d servername
  • 数据结构初阶 —— 树(堆)

    目录 一 xff0c 堆 堆的概念 向下调整法 xff08 数组 xff09 向上调整法 xff08 数组 xff09 堆的创建 xff08 建堆 xff09 堆的实现 一 xff0c 堆 堆的概念 如有个关键码的集合K 61 xff0c