树的初步了解及堆,堆的topk问题,堆排序

news2024/11/18 16:26:36

目录

前言 

一:树

1.树的概念

2.树的基础概念知识

3.在树中孩子节点和父节点知一求一 

4.树的表示方法

二:二叉树

1.二叉树的概念

2.二叉树的特性

3.满二叉树 

4.完全二叉树 

三:堆 

1.堆的定义

2.堆的实现:数组实现 

1.堆的结构定义

2.堆的实现 

3.堆排序 

第一种:直接排序

第二种:建堆实现 

 4.堆排序中向下调整建堆和向上调整建堆时间复杂度比较

1.向下调整建堆

2.向上调整建堆 

5.堆实现TopK 问题

TopK问题就是从N个数中找出最大或最小的前K个

1.正常思路

2.改进思路

3.TopK问题的实现(用文件进行操作)

四:结束语 


接下来的日子会顺顺利利,万事胜意,生活明朗-----------林辞忧

前言 

数据结构的树是一种较复杂的结构,包含多种分支结构,如完全二叉树,满二叉树,堆,以及更难理解的AVL树,B数,B+树等等,这些结构共同组成了树的庞大结构体系,接下来我们将初步了解关于树,堆等结构

一:树

1.树的概念

树是一种非线性的数据结构,是由N个节点连接而成,当N为0时称为空树

2.树的基础概念知识

3.在树中孩子节点和父节点知一求一 

知孩子节点算父亲节点:parent=(child-1)/2;

知父节点求孩子节点:child=parent*2+1(假设只有一个孩子)

4.树的表示方法

左孩子右兄弟表示法

二:二叉树

1.二叉树的概念

是n个节点连接而成的有限集合,分为根节点和根节点的左右子树,且两棵子树不相交

2.二叉树的特性

1.每个节点最多两棵子树,即不存在度为2以上的节点

2.二叉树的左右子树是有顺序,不能颠倒的,为有序树

3.满二叉树 

每一层都是满结点的二叉树

4.完全二叉树 

前h-1层都是满的,最后一层可以不满,但是从左往右是连续的

三:堆 

1.堆的定义

1.堆属于完全二叉树的一种,分为大根堆和小根堆

2.大根堆:树的任何一个父节点都大于或等于孩子节点

3.小根堆:树的任何一个父节点都小于或等于孩子节点

2.堆的实现:数组实现 

1.堆的结构定义

2.堆的实现 

#include "Heap.h"
//堆的初始化
void HeapInit(Heap* php)
{
	assert(php);
	php->a = NULL;
	php->capacity = php->size = 0;//指向最后一个有效数据的下一个
}
//堆的销毁
void HeapDestroy(Heap* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	php->capacity = php->size = 0;
}
//堆中插入数据
void HeapPush(Heap* php, HeapDataType x)
{
	assert(php);
	if (php->capacity == php->size)
	{
		int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
		HeapDataType* tmp = realloc(php->a, sizeof(HeapDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("malloc fail\n");
			return;
		}
		php->a = tmp;
		php->capacity = newcapacity;
	}
	php->a[php->size++] = x;
	

	//向上调整保持堆结构
	AdjustUp(php->a, php->size-1);

}

void Swap(HeapDataType* p1, HeapDataType* p2)
{
	HeapDataType tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

void AdjustUp(HeapDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child>0)
	{
		//小堆
		if (a[parent] > a[child])
		{
			//交换
			Swap(&a[parent], &a[child]);

			//迭代往上
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}
//删除堆顶元素
void HeapPop(Heap* php)
{
	assert(php);
	assert(!HeapEmpty(php));
	Swap(&php->a[0], &php->a[php->size - 1]);

	php->size--;

	//向下调整
	AdjustDown(php->a, php->size, 0);
}

void AdjustDown(int* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child] > a[child + 1])
		{
			child++;
		}

		if (a[parent] > a[child])
		{
			Swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
//判空
bool HeapEmpty(Heap* php)
{
	return php->size == 0;
}
//堆顶元素
HeapDataType HeapTop(Heap* php)
{
	return php->a[0];
}

3.堆排序 

堆排序作为一种排序方法,时间复杂度为O(N*log N),排序效率极佳,接下来我们将详细介绍

第一种:直接排序
void HeapSort(int* a, int n)
{
	Heap hp;
	HeapInit(&hp);
	int b[] = { 25,10,45,47,30,50 };
	int sz = sizeof(b) / sizeof(b[0]);
	for (int i = 0; i < sz; i++)
	{
		//插入数据调整为堆
		HeapPush(&hp, b[i]);
	}
	int i = 0;
	while (!HeapEmpty(&hp))
	{
		//再插入回数组
		int top = HeapTop(&hp);
		a[i++] = top;
		HeapPop(&hp);
	}
	printf("\n");
}

弊端:需要先写一个堆,太复杂

第二种:建堆实现 

 4.堆排序中向下调整建堆和向上调整建堆时间复杂度比较

1.向下调整建堆

2.向上调整建堆 

5.堆实现TopK 问题

TopK问题就是从N个数中找出最大或最小的前K个
1.正常思路

如果找N个数中最大的前K个,就得把N个数建为大堆,每Pop一次找到次大的数(Pop函数在每次Pop时会往下调整找出次大的数),Pop K次,即可找到前K个

如果当数据很大时,上面的思路就处理不了,比如N为10亿个整数,就得用4G的存储空间,此时数据就会存储在磁盘文件中,不允许随机访问等操作

2.改进思路

1.建立K个数的小堆

2.后N-K个数,依次与堆顶数据比较,大的话就替换入堆覆盖堆顶值,向下调整

3.最后这个小堆的值就是最大的前K个

3.TopK问题的实现(用文件进行操作)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void AdjustDown(int* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (a[child + 1] < a[child])
		{
			child++;
		}

		if (a[parent] > a[child])
		{
			int tmp = a[parent];
			a[parent] = a[child];
			a[child] = tmp;
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
void CreateNData()
{
	//造数据
	int n = 1000;
	srand( (unsigned int) time(0) );
	const char* file = "data.txt";
	FILE* fin = fopen(file, 'w');
	if (fin == NULL)
	{
		perror("fopen error\n");
		return;
	}
	for (size_t i = 0; i < n; i++)
	{
		int x = rand() % 1000000;
		fprintf(fin,"%d",x);
	}
	fclose(fin);
}
void PrintTopK(int k)
{
	const char* file = "data.txt";
	FILE* fout = fopen(file, 'r');
	if (fout == NULL)
	{
		perror("fopen error\n");
		return;
	}

	//建立k个数的小堆
	int* kminheap = (int*)malloc(sizeof(int) * k);
	if (kminheap == NULL)
	{
		perror("malloc fail\n");
		return;
	}

	for (int i = 0; i < k; i++)
	{
		fscanf(fout, "%d", &kminheap[i]);
	}

	//建小堆
	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(kminheap, k, i);
	}

	//堆顶元素和N-K个数据比较,大的话替换入堆
	int val = 0;
	while (!feof(fout))
	{
		fscanf(fout, "%d", &val);
		if (val > kminheap[0])
		{
			kminheap[0] = val;
			AdjustDown(kminheap, k, 0);
		}
	}
	//打印数据
	for (int i = 0; i < k; i++)
	{
		printf("%d ",kminheap[i]);
	}
	printf("\n");
}
int main()
{
	CreateNData();
	PrintTopK(5);
	return 0;
}

四:结束语 

在初步了解这些二叉树和堆的结构和实现后,可以更方便为以后学习打下基础

低头往前冲吧

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

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

相关文章

牛客网-SQL大厂面试题-2.平均播放进度大于60%的视频类别

题目&#xff1a;平均播放进度大于60%的视频类别 DROP TABLE IF EXISTS tb_user_video_log, tb_video_info; CREATE TABLE tb_user_video_log (id INT PRIMARY KEY AUTO_INCREMENT COMMENT 自增ID,uid INT NOT NULL COMMENT 用户ID,video_id INT NOT NULL COMMENT 视频ID,start…

【小白刷leetcode】第15题

【小白刷leetcode】第15题 动手刷leetcode&#xff0c;正在准备蓝桥&#xff0c;但是本人算法能力一直是硬伤。。。所以做得一直很痛苦。但是不熟练的事情像练吉他一样&#xff0c;就需要慢速&#xff0c;多练。 题目描述 看这个题目&#xff0c;说实在看的不是很懂。索性我们直…

YOLOv9算法原理——使用可编程梯度信息学习想要学习的内容

前言 2023年1月发布YOLOv8正式版后&#xff0c;经过一年多的等待&#xff0c;YOLOv9终于面世了&#xff01;YOLO是一种利用图像全局信息进行目标检测的系统。自从2015年Joseph Redmon、Ali Farhadi等人提出了第一代模型以来&#xff0c;该领域的研究者们已经对YOLO进行了多次更…

OceanBase4.2版本 Docker 体验

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

文件包含例子

一、常见的文件包含函数 php中常见的文件包含函数有以下四种&#xff1a; include() require() include_once() require()_once() include与require基本是相同的&#xff0c;除了错误处理方面: include()&#xff0c;只生成警告&#xff08;E_WARNING&#xff09;&#x…

Unity Live Capture 中实现面部捕捉同步模型动画

Unity Face Capture 是一个强大的工具&#xff0c;可以帮助你快速轻松地将真实人脸表情捕捉到数字模型中。在本文中&#xff0c;我们将介绍如何在 Unity Face Capture 中实现面部捕捉同步模型动画。 安装 |实时捕获 |4.0.0 (unity3d.com) 安装软件插件 安装 Live Capture 软件…

数据资产管理解决方案:构建高效、安全的数据生态体系

在数字化时代&#xff0c;数据已成为企业最重要的资产之一。然而&#xff0c;如何有效管理和利用这些数据资产&#xff0c;却是许多企业面临的难题。本文将详细介绍数据资产管理解决方案&#xff0c;帮助企业构建高效、安全的数据生态体系。 一、引言 在信息化浪潮的推动下&a…

为什么单线程的 Redis 能那么快?

大家好我是苏麟 , 给大家找一些好的文章看看 . 原文文章 : 03 高性能IO模型&#xff1a;为什么单线程Redis能那么快&#xff1f; (lianglianglee.com) Redis 为什么用单线程&#xff1f; 要更好地理解 Redis 为什么用单线程&#xff0c;我们就要先了解多线程的开销。 多线程的…

力扣hot100:416.分割等和子集(组合/动态规划/STL问题)

组合数问题 我们思考一下&#xff0c;如果要把数组分割成两个子集&#xff0c;并且两个子集的元素和相等&#xff0c;是否等价于在数组中寻找若干个数使之和等于所有数的一半&#xff1f;是的&#xff01; 因此我们可以想到&#xff0c;两种方式&#xff1a; ①回溯的方式找到t…

基于SpringBoot+Vue交流和分享平台的设计与实现(源码+部署说明+演示视频+源码介绍)

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通…

Android Studio实现内容丰富的安卓宠物用品商店管理系统

获取源码请点击文章末尾QQ名片联系&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动。 项目编号128 1.开发环境android stuido jdk1.8 eclipse mysql tomcat 2.功能介绍 安卓端&#xff1a; 1.注册登录 2.系统公告 3.宠物社区&#xff08;可发布宠物帖子&#…

如何将Git拉取项目后,将SSH验证方式修改为HTTPS?

首先在打开项目所在位置的Git BashGUI 查找当前的远程仓库URL&#xff1a; 打开终端或命令提示符&#xff0c;导航到你的项目目录&#xff0c;并使用以下命令查看当前配置的远程仓库URL&#xff1a; git remote -v这会显示如下格式的输出&#xff1a; origin gitgithub.com:用…

从政府工作报告探讨计算机行业的发展

从政府工作报告探计算机行业发展 政府工作报告作为政府工作的全面总结和未来规划&#xff0c;不仅反映了国家整体的发展态势&#xff0c;也为各行各业提供了发展的指引和参考。随着信息技术的快速发展&#xff0c;计算机行业已经成为推动经济社会发展的重要引擎之一。因此&…

什么是 KNIME Hub(2024)

什么是 KNIME Hub KNIME Hub 是一个中央存储库和协作平台&#xff0c;它是用来促进与 KNIME Analytics Platform(分析平台,AP)相关的工作流、节点、组件和扩展的共享和管理。它既充当工作流存储库又充当协作空间&#xff0c;使用户能够发现和利用可合并到其数据分析项目中的各种…

前端Prettier 插件的使用配置(详细)

各个参数代表的意思:printWidth&#xff1a;每行代码的最大长度限制。 tabWidth&#xff1a;选项用于控制制表符的宽度。 useTabs&#xff1a;指定是否使用制表符代替空格。 semi&#xff1a;指定是否在语句的末尾添加分号。 singleQuote&#xff1a;指定是否使用单引号或双引号…

控制学习_正弦波无刷直流力矩电机建模、控制带宽讨论与选择

无刷电机通过电子换向器实现定子的磁场旋转&#xff0c;去电刷后使用寿命大幅提升&#xff0c;是现在更流行的选择。三相无刷电机则是无刷电机中比较流行的一款。三相无刷电机的驱动方式有多种&#xff0c;最简单的被称为梯形波驱动、方波驱动或正弦波驱动。而正弦波驱动技术可…

Redis中的HyperLogLog以及HyperLogLog原理

大家在学习redis的过程中&#xff0c;除了String&#xff0c;list&#xff0c;hash&#xff0c;set&#xff0c;zset这五种基本的数据结构&#xff0c;一定还会接触到几种高级的数据结构&#xff0c;比如bitmap&#xff0c;geo&#xff0c; 还有今天我们要说的hyperloglog&…

【OJ】string类题目

个人主页 &#xff1a; zxctscl 如有转载请先通知 题目 1. 415字符串相加1.1 分析1.2 代码 2. 344反转字符串2.1 分析2.2 代码 3. HJ1字符串最后一个单词的长度3.1 分析3.2 代码 4. 387.字符串中的第一个唯一字符4.1 分析4.2 代码 5. 125验证回文串5.1 分析5.2 代码 1. 415字符…

ctf-web23

web23 substr substr:字符串截取&#xff1b;substr()函数可以用于字符串处理、数据清洗、数据挖掘等领域。 substr(abcdef,2,2)返回值cd PHP intval() 函数 ​编辑PHP 可用的函数 intval() 函数用于获取变量的整数值。 intval() 函数通过使用指定的进制 base 转换&…

2000-2021年各省外商直接投资水平面板数据(含原始数据+计算结果)(无缺失)

2000-2021年各省外商直接投资水平面板数据&#xff08;含原始数据计算结果&#xff09;&#xff08;无缺失&#xff09; 1、时间&#xff1a;2000-2021年 2、指标&#xff1a;外商直接投资额&#xff08;万美元&#xff09;、外商直接投资额&#xff08;万元&#xff09;、国…