【数据结构和算法初阶(C语言)】二叉树的顺序结构--堆的实现/堆排序/topk问题详解---二叉树学习日记②

目录

​编辑

1.二叉树的顺序结构及实现

1.1 二叉树的顺序结构

2 堆的概念及结构

3 堆的实现

3.1堆的代码定义

3.2堆插入数据

3.3打印堆数据

3.4堆的数据的删除

3.5获取根部数据

3.6判断堆是否为空

3.7 堆的销毁 

4.建堆以及堆排序 

4.1 升序建大堆,降序建小堆

4.2堆排序

4.3 topk问题

5.结语


1.二叉树的顺序结构及实现

1.1 二叉树的顺序结构

普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结 构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统 虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

左孩子的下标 = 父亲下标*2+1

右孩子下标 = 父亲节点下标*2+2

父亲节点下标 = (子节点下标-1)/2 

2 堆的概念及结构

堆是非线性结构,是完全二叉树

如果有一个值的集合K = { , , ,…, },把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中,并满足: = 且 >= ) i = 0,1, 2…,则称为小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。 堆的性质: 堆中某个节点的值总是不大于或不小于其父节点的值;

堆总是一棵完全二叉树。

通俗来说父节点小于等于子节点的完全二叉树就叫小根堆,或者小堆,根一定是整棵树最小的。

父节点值大于等于子节点的完全二叉树叫做大根堆。或者大堆,但是底层数组不一定降序。但是大堆的根是整棵树的最大值。

3 堆的实现

3.1堆的代码定义

底层是一个顺序表

typedef int HPDataType;

typedef struct Heap
{
	//底层是一个顺序表,但是数据不是随便存储,逻辑结构是二叉树
	HPDataType * a;
	int size;
	int capacity;
}HP;

堆的初始化:

void HeapInit(HP* php)
{
	assert(php);
	HPDataType* tmp = (HPDataType*)malloc(sizeof(HPDataType) * 2);//先为i堆空间申请两个节点
	if (tmp == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	
	php->a = tmp;
	php->capacity = 2;
	
	php->size = 0;
}

 

3.2堆插入数据

实现关键

实现原理图:向上调整:

(以大堆的实现方式举例)

首先我们从有限个数据的层面来实现一下堆的实现,后面堆排序再来看对于一堆数据怎么建堆。

对于一组少量数据比如一个数组:

首先将数据一个一个插入到堆里面,由于数据有限可以使用这种数据插入的方式建立堆这种数据结构;

void HeapPush(HP* php, HPDataType x)
{
	//尾插

	assert(php);
	//判断空间够不够
	if (php->capacity == php->size)
	{
		HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(php->a) + sizeof(HPDataType) * 2);
		if (tmp == NULL)
		{
			perror("realloc");
			exit(-1);
		}
		php->a = tmp;
		php->capacity += 2;
	}
	php->a[php->size] = x;
	php->size++;
	//调整数据,变成堆
	AdjustUp(php->a, php->size-1);
	
}

 然后把这组数据调整成一个堆:

 

void Swap(HPDataType* child, HPDataType* parent)
{
	HPDataType tmp = 0;
	tmp = *child;
	*child = *parent;
	*parent = tmp;
}
void AdjustUp(HPDataType* a,int child)//向上调整
{
	//最坏调整到根
	int parent = (child - 1) / 2;
	while (child>0)//注意这个判断条件
	{
		if (a[child] > a[parent])
		{
			//交换
			Swap(&a[child], &a[parent]);
			//继续往上深入判断,将父亲的下标给孩子,父亲的父亲的下标给父亲
			child = parent;
			parent = (parent - 1) / 2;
		}
		else
		{
			break;//跳出循环
		}
	}

}

3.3打印堆数据

为了看一下我们插入的效果我们来试一下插入一段数据 

 

void HeapPrint(HP* php)
{
	assert(php); 
	for (int i = 0; i < php->size; i++)
	{
		printf("%d ", php->a[i]);
		
	}
}

 

 就建成了一个大堆。

3.4堆的数据的删除

堆这个数据结构有意义的一个点就是,大堆的根一定是这组数据中最大的值,小堆的根一定是这组数据中最小的值。所以如果我们能拿到这个根的数据,再删除就可以找到这堆数据中次小的数据了。那么删除根数据是这个结构比较有意义的。

想一个问题:根的删除能不能简单的数据覆盖?只是将后续的数据移动向前

答案是不能的,可以数据这样移动后续数据根本就不能成堆了。那么这里使用的方法是向下调整法

前提是左右子树是堆:

这里我们以小堆举例示范:

先删除

void HeapPop(HP* php) 
{
	assert(php);
	//不可挪动覆盖。可能就不是堆了
	//先交换根和最后一个值,再删除,左右子树依旧是小堆
	//向下调整的算法,左右子树都是小堆或者大堆。
	 
	assert(php->size > 0);
	Swap(&php->a[0],&php->a[php->size-1]);
	php->size--;//删除了数据
	AdjustDown(php->a,php->size, 0);
}

在调整

void AdjustDown(HPDataType* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child<n)
	{
		if (child+1<n&&a[child + 1] < a[child])//child+1可能越界访问
		{
			child++;
		}
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			//继续向下调整
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}

}

调整是由于每次都是取两个子节点中的较小的值,所以先假设一个大,如果假设错了,就改变下标 

if (child+1<n&&a[child + 1] < a[child])//child+1可能越界访问
        {
            child++;
        }

对调整循环结束的判定所示孩子下标小于n

3.5获取根部数据

//获取根部数据
HPDataType HeapTop(HP* php)
{
	assert(php);
	assert(php->size > 0);
	return php->a[0];
}

3.6判断堆是否为空


//判断堆是否为空函数
bool HeapEmpty(HP* php)
{
	assert(php);
	return php->size == 0;

}

3.7 堆的销毁 

void HeapDestory(HP* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	php->size = php->capacity = 0;
}

那么如果现在我们每次拿到堆的元素在删除在获取,就可以得到一个有序的数据了:

4.建堆以及堆排序 

上面我们已经掌握了堆这个数据结构的一些方法,最后通过插入数据建堆。删除1数据将数据排序。可是如果我有十亿个数据,想找出最大的十个数据,如果用堆得插入10亿次数据吗?那就失去了使用这个数据结构的意义,通常来说我们只用建立一个大堆模型,这个堆的前十个数据自然就是10亿个数据中的最大的一个。

4.1 升序建大堆,降序建小堆

4.2堆排序

4.3 topk问题

 TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。

比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。 对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据量非常大,排序就不太可取了(可能 数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,

基本思路如下:

1. 用数据集合中前K个元素来建堆 前k个最大的元素,则建小堆 前k个最小的元素,则建大堆

2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。

(明天补)

5.结语

以上就是本期的所有内容,知识含量蛮多,大家可以配合解释和原码运行理解。创作不易,大家如果觉得还可以的话,欢迎大家三连,有问题的地方欢迎大家指正,一起交流学习,一起成长,我是Nicn,正在c++方向前行的奋斗者,数据结构内容持续更新中,感谢大家的关注与喜欢。

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RPM与DNF的操作实践

这几课有三个目标&#xff1a; 第一步&#xff1a;先配置软件源 跳转到yum.repos.d目录&#xff0c;用vim创建一个openeuler_x84_64.repo文件。这个文件就是我们将会用到的软件源。 我们在里面添加这些东西&#xff0c;保存并退出即可。 然后&#xff0c;我们用yum list all就…

【CICD】Jenkins 常用操作手册

常见词汇 词汇 说明 Node 作为 Jenkins 环境的一部分并能够执行Pipeline或项目的机器&#xff0c;无论是 Master 还是Agent 都被认为是 Node。 Master 存储配置&#xff0c;加载插件以及为 Jenkins 呈现各种用户界面的主控节点 Agent 通常是一台主机或容器&#xff0c;连…

Hive:数据仓库利器

1. 简介 Hive是一个基于Hadoop的开源数据仓库工具&#xff0c;可以用来存储、查询和分析大规模数据。Hive使用SQL-like的HiveQL语言来查询数据&#xff0c;并将其结果存储在Hadoop的文件系统中。 2. 基本概念 介绍 Hive 的核心概念&#xff0c;例如表、分区、桶、HQL 等。 …

Chrome历史版本下载地址:Google Chrome Older Versions Download (Windows, Linux Mac)

最近升级到最新版本Chrome后发现页面居然显示错乱,是在无语, 打算退回原来的版本, 又发现官方只提供最新的版本下载, 为了解决这个问题所有收集了Chrome历史版本的下载地址分享给大家. Google Chrome Windows version 32-bit VersionSizeDate104.0.5112.10279.68 MB2022-05-30…

TT-100K数据集,YOLO格式

TT-100K数据集YOLO格式&#xff0c;分为train、val和test&#xff0c;其中train中共有6793张图片&#xff0c;val中共有1949张图片&#xff0c;test中共有996张图片。数据集只保留包含图片数超过100的类别。共计46类。

uniapp微信小程序随机生成canvas-id报错?

uniapp微信小程序随机生成canvas-id报错&#xff1f; 文章目录 uniapp微信小程序随机生成canvas-id报错&#xff1f;效果图遇到问题解决 场景&#xff1a; 子组件&#xff0c;在 mounted 绘制 canvas&#xff1b;App、H5端正常显示&#xff0c;微信小程序报错&#xff1b; 效…

信息系统项目管理师019:存储和数据库(2信息技术发展—2.1信息技术及其发展—2.1.3存储和数据库)

文章目录 2.1.3 存储和数据库1.存储技术2.数据结构模型3.常用数据库类型4.数据仓库 记忆要点总结 2.1.3 存储和数据库 1.存储技术 存储分类根据服务器类型分为&#xff1a;封闭系统的存储和开放系统的存储。封闭系统主要指大型机等服务器。开放系统指基于包括麒麟、欧拉、UNIX…

MacBook远程桌面Windows使用Microsoft Remote Desktop for Mac_亲测使用

MacBook远程桌面Windows使用Microsoft Remote Desktop for Mac_亲测使用 像Windows上有自带的远程桌面连接软件.MacBook没有自带的远程连接Windows桌面的工具,需要安装软件来实现. 像远程桌面控制软件一般有 TeamViewer、向日葵远程控制, ToDesk, Microsoft Remote Desktop f…

【ZooKeeper3、Watcher机制

本文基于 Apache ZooKeeper Release 3.7.0 版本书写 作于 2022年5月15日 17:22:11 转载请声明 演示前的ZooKeeper目录状态&#xff0c;只有zookeeper默认目录&#xff1a; 在客户端直接输入 --help 命令&#xff0c;可以看到以下文字&#xff1a; 可以看到 addWatch 命令&am…

视频桥接芯片#LT8912B适用于MIPIDSI转HDMI+LVDS应用方案,提供技术支持。

1. 概述 Lontium LT8912B MIPI DSI 转 LVDS 和 HDMI 桥接器采用单通道 MIPI D-PHY 接收器前端配置&#xff0c;每通道 4 个数据通道&#xff0c;每个数据通道以 1.5Gbps 的速度运行&#xff0c;最大输入带宽高达 6Gbps。 对于屏幕应用&#xff0c;该桥接器可解码 MIPI DSI 18bp…

【QED】斐波那契游戏

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 总结 题目 题目链接&#x1f517; 斐波那契数列指的是这样一个数列&#xff1a;1&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;8&#xff0c;13&#xff0c;21&#xff0c;34&#xff0c;55&#x…

Docker部署TeamCity来完成内部CI、CD流程

使用TeamCity来完成内部CI、CD流程 本篇教程主要讲解基于容器服务搭建TeamCity服务&#xff0c;并且完成内部项目的CI流程配置。至于完整的DevOps&#xff0c;我们后续独立探讨。 一个简单的CI、CD流程 以下分享一个简单的CI、CD流程&#xff08;仅供参考&#xff09;&#…

C++进阶之路---手撕“红黑树”

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、红黑树的概念与性质 1.概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点…

大数据开发-数据仓库简介

文章目录 什么是数据仓库数据仓库基础知识数据仓库的建模方式数据仓库分层数据仓库的命名规范典型数仓系统架构 什么是数据仓库 数据仓库(Data Warehouse)是一个面向主题的、集成的、稳定的且随时间变化的数据集合&#xff0c;用于支持管理人员的决策 面向主题&#xff1a;类…

怎么做好独立站的SEO优化

随着全球贸易的蓬勃发展&#xff0c;越来越多的企业开始关注外贸市场&#xff0c;并将目光投向了外贸网站。然而&#xff0c;在竞争激烈的外贸市场中&#xff0c;如何写出吸引人的文章&#xff0c;以及如何优化网站以在搜索引擎中脱颖而出&#xff0c;成为了外贸独立网站必须面…

前端 -- 基础 表单标签 -- 表单域

表单域 # 表单域是一个包含 表单元素 的区域 在 HTML 标签中&#xff0c; <form> 标签 用于定义表单域&#xff0c; 以实现用户信息的收集和传递 简单通俗讲&#xff0c; 就是 <form> 会把它范围内的表单元素信息提交给后台&#xff08;服务器) 对于上面讲…

外贸网站文章批量生成器

随着全球贸易的不断发展&#xff0c;越来越多的企业开始关注外贸市场&#xff0c;而拥有高质量的内容是吸引潜在客户的关键之一。然而&#xff0c;为外贸网站生产大量优质的文章内容可能是一项耗时且繁琐的任务。因此&#xff0c;外贸网站文章批量生成软件成为了解决这一难题的…

MATLAB教程

目录 前言一、MATLAB基本操作1.1 界面简介1.2 搜索路径1.3 交互式命令操作1.4 帮助系统 二、MATLAB语言基础2.1 数据类型2.2 MATLAB运算2.2.1 算数运算2.2.2 关系运算2.2.3 逻辑运算 2.3 常用内部函数2.4 结构数据与单元数据 三、MATLAB程序设计3.1 M文件3.2 函数文件3.3 程序控…

1688商品详情API接口采集商品上货

阿里巴巴1688平台并没有直接公开商品详情API接口供普通用户或开发者进行商品采集和上货。1688平台主要服务于批发和采购业务&#xff0c;其API服务通常面向的是有深度合作关系的商家或开发者&#xff0c;且需要经过申请和审核流程。 请求示例&#xff0c;API接口接入Anzexi58 …

【重温设计模式】观察者模式及其Java示例

观察者模式的概念和原理 在编程世界中&#xff0c;设计模式作为一种解决问题的策略&#xff0c;它的存在就如同人类语言中的成语&#xff0c;是一种经过时间考验的有效解决方案。 观察者模式就是其中一种重要的设计模式&#xff0c;它在很多场景中都有着广泛的应用。那么&…
最新文章