数据结构7—树(顺序存储二叉树—堆)含TOPK问题

news2024/12/24 10:09:34

1.树

1.1树的概念与结构

树是一种非线性的数据结构,它是由 n(n >= 0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一颗倒挂的树,也就是说它是根朝上,而叶朝下的。

  • 有一个特殊的结点,称之为根结点(只能有一个),根结点没有前驱结点。
  • 每颗字树的根结点有且只有一个前驱,可以有0个或多个后继。因此,树是递归定义的。
  • 子树是不相交的(如果存在相交,那就变成图了)
  • 除了根结点外,每个结点有且仅有一个父结点
  • 一颗N个结点的树有N-1个边

1.2相关术语

  • 父结点/双亲结点:若一个结点含义子节点,则这个结点称为其子结点的父结点。A是B的父结点,A是C的父结点。
  • 子结点/孩子结点:一个结点含有的子树的根结点称为该结点的子结点。B是A的子结点。
  • 结点的度:一个结点有几个孩子,它的度就是多少。A的度为2,B的度为3。
  • 树的度:一棵树中,最大的结点的度。上图:树的度为3。
  • 叶子结点/终端结点:度为0的结点称为叶结点。D、H、I、F、G。
  • 分支结点/非终端结点:度不为0的结点。B、C、E。
  • 兄弟结点:具有相同父结点的结点互称为兄弟结点(亲兄弟)。B和C就是兄弟结点。
  • 结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推。
  • 树的高度或深度:树中结点的最大层次。上图为4。
  • 结点的祖先:从根到该结点所经分支上的所有结点。A是所有结点的祖先。
  • 路径:一条从树中任意结点出发,沿父结点—子结点连接,达到任意结点的序列。比如A到H:A—B—E—H。
  • 子孙:以某结点为根的子树中任一结点都称为该结点的子孙。所有结点都是A的子孙。
  • 森林:有m(m > 0)棵互不相交的树集合称为森林。

1.3树的表示

孩子兄弟表示法:

树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦,既要保存值域,也要保存结点和结点之间的关系,实际中树有很多种表示方法如:双亲表示法,孩子表示法,孩子双亲表示法以及孩子兄弟教师法等。但此刻就介绍最常用的:孩子兄弟表示法。

struct TreeNode
{
   struct TreeNode* child;    //左边开始的第一个孩子结点
   struct TreeNode* brother;  //指向其右边的下一个兄弟结点
   int data;                  //结点中的数据域
}

1.4树形结构实际运用场景

文件系统是计算机存储和管理文件的一种方式,它利用树形结构来组织和管理文件和文件夹。在文件系统中,树的结构被广泛应用,它通过父结点和子结点之间的关系来表示不同层级的文件和文件夹之间的关联。

2.二叉树

2.1概念与结构

在树形结构中,我们最常用的就是二叉树,一颗二叉树是结点的一个有限集合,该集合由一个根结点加上两颗别称为左子树和右子树的二叉数组组成或者为空。 

2.2特殊的二叉树

2.2.1满二叉树

一个二叉树,如果每一层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为k,且结点总数是2的k次方-1,则它就是满二叉树。

2.2.2完全二叉树

完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来。对于深度为k的,有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。满二叉树是一种特殊的完全二叉树。(假设有K层,最后一层从左到右放,但是K-1包括K-1之前的层数都达到了最大)

2.3二叉树存储结构

二叉树一般可以使用两种结构存储,一种顺序结构,一种链式结构。

2.3.1顺序结构

顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费,完全二叉树更适合使用顺序结构存储。

2.3.2链式结构

二叉树的链式结构是指,用链表来表示一颗二叉树,即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址。

3.实现顺序结构的二叉树

一般堆使用顺序结构的数组来存储数据,堆是一种特殊的二叉树,具有二叉树的特性的同时,还具备其他的特性。

3.1堆

  • 若 i > 0,i 位置结点的双亲序号:(i - 1)/ 2;i = 0,i 为根结点编号,无双亲结点
  • 若 2i +1 < n,左孩子序号:2i+1       右孩子序号:2i+2

4.源代码

Heap.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <time.h>

typedef int DataType;
//定义堆的结构——数组
typedef struct Heap
{
	DataType* arr;
	int size;//有效数据个数
	int capacity;//空间大小
}HP;

void HPInit(HP* php);//初始化

void HPDestroy(HP* php);//销毁

void HPPush(HP* php,DataType x);//插入

void HPPop(HP* php);//删除

DataType HPTop(HP* PHP);//出堆顶元素

bool HPEmpty(HP* php);//true为空,false为不空

void ADJustDown(DataType* arr, int parent, int n);//向下调整算法

void ADJustUp(DataType* arr, int child);//向上调整算法

Heap.c

#include "Heap_Tree.h"

void HPInit(HP* php)
{
	assert(php);
	php->arr = NULL;
	php->size = php->capacity = 0;
}

void HPDestroy(HP* php)
{
	assert(php);
	if(php->arr)
	    free(php->arr);
	php->arr = NULL;
	php->size = php->capacity = 0;
}

void Swap(int* x, int* y)
{
	int temp = *x;
	*x = *y;
	*y = temp;
}
void ADJustUp(DataType* arr,int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		//大堆:>
		//小堆:<
		if (arr[child] < arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

void HPPush(HP* php, DataType x)
{
	assert(php);
	//判断空间是否足够
	if (php->size == php->capacity)
	{
		//扩容
		int newcapacity = php->capacity == 0 ? 4 : 2 * php->capacity;
		DataType* tmp = (DataType*)realloc(php->arr, newcapacity*sizeof(DataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		php->arr = tmp;
		php->capacity = newcapacity;
	}
	php->arr[php->size] = x;

	ADJustUp(php->arr, php->size);
	php->size++;
}

void ADJustDown(DataType* arr,int parent,int n)
{
	int child = parent * 2 + 1;//左孩子
	while (child<n)
	{
		if (child+1<n && arr[child] > arr[child + 1])
		{
			child++;
		}
		if (arr[child] < arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			parent = child;
			child = parent * 2 - 1;	
		}
		else
		{
			break;
		}
	}
}

void HPPop(HP* php)
{
	assert(php && php->size);

	Swap(&php->arr[0], &php->arr[php->size - 1]);
	php->size--;
	ADJustDown(php->arr,0,php->size);
}

bool HPEmpty(HP* php)
{
	assert(php);
	return php->size == 0;
}


DataType HPTop(HP* php)
{
	assert(php && php->size);

	return php->arr[0];
}

//堆排序
void HeapSort(int* arr,int n)
{
	//向上调整算法建堆(小堆)
	for (int i = 0; i < n; i++)
	{
		ADJustUp(arr,i);
	}
	//向下调整算法建堆(大堆)
	for (int i=(n-2)/2;i>=0;i--)
	{
		ADJustDown(arr,i,n);
	}
	//升序(用大堆+向下调整算法)
	int end = n - 1;
	while (end>0)
	{
		Swap(&arr[0],&arr[end]);
		ADJustDown(arr, 0, end);
		end--;
	}
}

4.1 TOPK问题

#include "Heap_Tree.h"

void test01()
{
	HP hp;
	HPInit(&hp);
	int arr[] = {17,20,10,13,19,15 };
	for (int i = 0; i < 6; i++)
	{
		HPPush(&hp,arr[i]);
	}


	while (!HPEmpty(&hp))
	{
		printf("%d ", HPTop(&hp));
		HPPop(&hp);
	}
	HPDestroy(&hp);
}

void CreateNDate()
{
	//造数据
	int n = 100000;
	srand(time(0));
	const char* file = "data.txt";
	FILE* fin = fopen(file,"w");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}
	for (int i=0;i<n;i++)
	{
		int x = (rand() + i) % 100000;
		fprintf(fin, "%d\n", x);
	}
	fclose(fin);
}

void TOPK()
{
	int k = 0;
	printf("请输入K:");
	scanf("%d",&k);

	//从文件中读取前K个数据,建堆
	const char* file = "data.txt";
	FILE* fout = fopen(file, "r");
	if (fout == NULL)
	{
		perror("fepen fail");
		exit(1);
	}
	int* minHeap = (int*)malloc(k * sizeof(int));
	if (minHeap == NULL)
	{
		perror("malloc fail");
		exit(2);
	}
	//从文件读取k个数据,开始建堆
	for (int i=0;i<k;i++)
	{
		fscanf(fout,"%d",&minHeap[i]);
	}
	//建小堆
	for (int i = (k-1-1)/2; i >=0 ; i--)
	{
		ADJustDown(minHeap,i,k);
	}
	int x = 0;
	while (fscanf(fout,"%d",&x)!=EOF)
	{
		//读取到的数据跟堆顶的数据进行比较
		//比堆顶大,就交换入堆
		if (x > minHeap[0])
		{
			minHeap[0] = x;
			ADJustDown(minHeap, 0, k);
		}
	}
	for (int i = 0; i < k; i++)
	{
		printf("%d ", minHeap[i]);
	}


	fclose(fout);
}

int main()
{
	//test01();
	//CreateNDate();
	TOPK();


	return 0;
}

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

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

相关文章

Linux 安装JDK8和卸载

目录 一、下载JDK8的rpm包 二、安装JDK 三、设置环境变量 Linux环境下安装JDK的方式有多种&#xff0c;可以通过rpm包、yum安装或者tar.gz压缩包。本章节会教大家通过前两者方式来安装JDK&#xff0c;压缩包的形式因为下载压缩包后上传到服务器环境下&#xff0c;将压缩包解…

1.6 计算机网络体系结构

参考&#xff1a;&#x1f4d5;深入浅出计算机网络 常见的三种计算机网络体系结构 TCP/IP体系结构 路由器一般只包含网络接口层和网际层。 应用层TCP/IP体系结构的应用层包含了大量的应用层协议&#xff0c;例如HTTP、SMTP、DNS、RTP等运输层TCP和UDP是TCP/IP体系结构运输层的…

召回的在线评估与离线评估

在现代信息检索、推荐系统等应用场景中&#xff0c;召回阶段扮演着至关重要的角色。召回系统负责从海量候选项中筛选出潜在相关的内容&#xff0c;因此其效果直接影响用户的满意度和系统的效率。为了确保召回系统的性能&#xff0c;我们需要对其进行评估&#xff0c;而评估方法…

Python3爬虫教程-HTTP基本原理

HTTP基本原理 1&#xff0c;URL组成部分详解2&#xff0c;HTTP和HTTPS3&#xff0c;HTTP请求过程4&#xff0c;请求&#xff08;Request&#xff09;请求方法&#xff08;Request Method&#xff09;请求的网址&#xff08;Request URL&#xff09;请求头&#xff08;Request H…

Cilium + ebpf 系列文章-ebpf-map(二)

前言: 上一章节讲述了什么是:ebpf. Cilium + ebpf 系列文章-什么是ebpf?(一)-CSDN博客一、We Create a container be a Server.二、We Create a container be a Client.三、Them link at a Bridge.四、 Do test.一、Test-tools。3、当你执行l s操作时,会调用open的系统调…

Vulkan 学习(8)---- vkImageView 创建

目录 OverView创建方法关键结构参考代码 OverView Vulkan 的图像视图(VkImageView) 用于描述如何访问 VkImage 对象以及访问图像的哪一部分, 图像视图定义了图像格式和访问方式&#xff0c;允许渲染管线和图像进行交互&#xff0c;无论是作为纹理&#xff0c;颜色附件或者深度…

HTTP.SYS远程代码执⾏(MS15-034) MS-->Microsoft 2015 -034

环境 windows server 2012 IIS8.5 复现 1.访问⽹站 2.主⻚图⽚ iis8.5的是&#xff08;iis-85.png&#xff09;&#xff0c;其他的可以根据百度查&#xff0c;每个版本的欢迎⻚都不⼀样 3.编辑请求头&#xff0c;增加Range: bytes0-18446744073709551615字段&#xff0c;若…

车路云一体化大模型数据治理方案

车路云一体化大模型数据治理解决方案 "杭州市发改委已批复了杭州交通投资集团的智能网联汽车“车路云一体化”试点项目。这一批复体现了其对该项目可行性研究报告的肯定&#xff0c;预示着杭州市在智能驾驶领域的进一步发展。" 2024年6月18日&#xff0c;第十一届国…

Spring Boot集成Redis Search快速入门Demo

1.什么是Redis Search&#xff1f; RedisSearch 是一个基于 Redis 的搜索引擎模块&#xff0c;它提供了全文搜索、索引和聚合功能。通过 RedisSearch&#xff0c;可以为 Redis 中的数据创建索引&#xff0c;执行复杂的搜索查询&#xff0c;并实现高级功能&#xff0c;如自动完…

简历技能面试问答

变成语言和开发工具 C新特性 自动类型推导 (auto)&#xff1a; 自动推导变量的类型&#xff0c;减少显式类型声明的繁琐 范围 for 循环&#xff1a; 用于遍历容器或数组&#xff0c;简化代码。 nullptr&#xff1a; nullptr 取代 NULL&#xff0c;表示空指针&#xff0c;类…

出海企业如何利用海外云手机开展业务?

随着全球化的持续推进&#xff0c;越来越多的企业将目光投向海外市场。然而&#xff0c;面对不同国家的网络环境、政策限制以及文化和语言的差异&#xff0c;出海企业在拓展海外业务时遇到了许多障碍。海外云手机作为一种创新的解决方案&#xff0c;为企业提供支持和帮助。 海外…

【高阶用法】uniapp的i18n/修复/增强/App无重启更换语言

痛点 在i18n多语言模块使用过程中&#xff0c;发现下面几个问题&#xff0c;需要解决 1&#xff09;uni-best框架下&#xff0c;$t功能函数无法实时的切换语言&#xff0c;可能跟使用有关 2&#xff09;uni-best建议的translate方式在vue块外使用太繁琐&#xff0c;希望不用…

verilog中非阻塞多个if 优先级判断。

always(posedge clk)beginz < 0;if(sel0)z < a;if(sel1)z < b;if(sel2)z < c;if(sel3)z < d;end 比如上述代码&#xff0c;最后一级的优先级最高。

深入理解 JavaScript 三大作用域:全局作用域、函数作用域、块级作用域

一. 作用域 对于多数编程语言&#xff0c;最基本的功能就是能够存储变量当中的值、并且允许我们对这个变量的值进行访问和修改。那么有了变量之后&#xff0c;应该把它放在哪里、程序如何找到它们&#xff1f;是否需要提前约定好一套存储变量、访问变量的规则&#xff1f;答案…

Teams会议侧边栏应用开发-会议转写

Teams应用开发&#xff0c;主要是权限比较麻烦&#xff0c;大量阅读和实践&#xff0c;摸索了几周&#xff0c;才搞明白。现将经验总结如下&#xff1a; 一、目标&#xff1a;开发一个Teams会议的侧边栏应用&#xff0c;实现会议的实时转写。 二、前提&#xff1a; 1&#x…

株洲芦淞大桥事故的深刻反思

株洲芦淞大桥事故的深刻反思 2024年9月23日清晨&#xff0c;株洲芦淞大桥上发生了一起令人痛心的交通事故&#xff0c;一辆白色小汽车被出租车追尾后失控&#xff0c;冲向对向车道&#xff0c;最终酿成6人死亡、多人受伤的惨剧。 这起事故不仅给受害者家庭带来了无法弥补的伤…

【Python机器学习系列】开发Streamlit应用程序并部署机器学习模型(案例+源码)

这是我的第357篇原创文章。 一、引言 近年来&#xff0c;随着机器学习和人工智能技术的迅猛发展&#xff0c;越来越多的研究者选择将他们的模型以应用程序&#xff08;App&#xff09;的形式进行部署&#xff0c;从而使审稿人和其他研究者可以通过简单的界面&#xff0c;输入相…

9月23日

头文件 // My_string.h #ifndef MY_STRING_H #define MY_STRING_H#include <cstring> #include <algorithm>class My_string { private:char* data;size_t length;void resize(size_t new_length) {size_t new_capacity std::max(new_length 1, length);char* n…

一种求解城市场景下无人机三维路径规划的高维多目标优化算法,MATLAB代码

在城市环境下进行无人机三维路径规划时&#xff0c;需要考虑的因素包括高楼、障碍物、飞行安全和效率等。为了解决这些问题&#xff0c;研究者们提出了多种算法&#xff0c;包括基于智能优化算法的方法。 首先&#xff0c;无人机航迹规划问题的数学模型需要考虑无人机的基本约…

用Flowise+OneAPI+Ollama做一个在线翻译工作流

用FlowiseOneAPIOllama做一个在线翻译工作流&#xff0c;输入一种语言&#xff0c;马上翻译成另外一种语言&#xff0c;使用到的结点主要有&#xff0c;ChatLLM、提示词模板还有LLM Chain。 一、设置OneAPI和Ollama 1、Ollama的安装及配置&#xff0c;请参考&#xff1a;在ub…