Topk问题以及二叉树的三种层序遍历和基本操作

一、Topk问题

1、问题描述

TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。

2、思路

对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据量非常大,排序就不太可取了(可能
数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:
1. 用数据集合中前K个元素来建堆
前k个最大的元素,则建小堆
前k个最小的元素,则建大堆
2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素
将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。

3、代码实现

首先通过文件函数生成100000个数据:
 

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) % 10000000;fprintf(fin, "%d\n", x);}fclose(fin);
}

在前面我们了解到若为向下建堆则为O(N);而向上建堆为O(N*logN);所以我们在这采用向下建堆:

void AdjustDown(HPDataType* a, int n, int parent)
{// 先假设左孩子小int child = parent * 2 + 1;while (child < n)  // child >= n说明孩子不存在,调整到叶子了{// 找出小的那个孩子if (child + 1 < n && a[child + 1] < a[child]){++child;}if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}
void TestHeap3()
{int k;printf("请输入k>:");scanf("%d", &k);int* kminheap = (int*)malloc(sizeof(int) * k);//开辟空间if (kminheap == NULL){perror("malloc fail");return;}const char* file = "data.txt";//打开我们刚刚创建的文件FILE* fout = fopen(file, "r");if (fout == NULL){perror("fopen error");return;}// 读取文件中前k个数for (int i = 0; i < k; i++){fscanf(fout, "%d", &kminheap[i]);}// 建K个数的小堆for (int i = (k - 1 - 1) / 2; i >= 0; i--){AdjustDown(kminheap, k, i);}// 读取剩下的N-K个数int x = 0;while (fscanf(fout, "%d", &x) > 0){if (x > kminheap[0]){kminheap[0] = x;//堆顶数据始终是最小的不可能出现卡住数据进不去问题AdjustDown(kminheap, k, 0);}}printf("最大前%d个数:", k);for (int i = 0; i < k; i++){printf("%d ", kminheap[i]);}printf("\n");
}

二、二叉树的三种层序遍历

以下三种遍历,如果树的深度太深就会栈溢出。

1、二叉树前序遍历

void PreOrder(BTNode* root)
{if (root == NULL){printf(" null ");return;}printf("%d ", root->_data);PreOrder(root->_left);PreOrder(root->_right);
}

递归调用图:

剩下的两种遍历流程图与其类似,这里不做详细图解。 

2、二叉树中序遍历

// 二叉树中序遍历
void InOrder(BTNode* root)
{if (root == NULL){printf(" null ");return;}InOrder(root->_left);printf("%d ", root->_data);InOrder(root->_right);
}

3、二叉树的后序遍历 

// 二叉树后序遍历
void PostOrder(BTNode* root)
{if (root == NULL){printf(" null ");return;}PostOrder(root->_left);PostOrder(root->_right);printf("%d ", root->_data);
}

三、树相关的计算

1、节点数的计算

节点数的计算可分为左树+右树 +1;

int treesize(BTNode* root)
{if (root == NULL) {return 0;}return treesize(root->_left) + treesize(root->_right);
}

2、叶字节点数

为空,叶为0,非空为左叶子数+右叶子数,结束条件为该节点左右两个子节点为空,或者该节点为空

int treeleaf(BTNode* root)
{if (root == NULL){return 0;}if (root->_left == NULL && root->_right == NULL){return 1;}return treeleaf(root->_left) + treeleaf(root->_right);
}

3、深度

若为空则高度为0,非空为左数高度与右数高度大的那一个

int treeleafhigh(BTNode* root)
{if (root == NULL){return 0;}int lefthigh = treeleafhigh(root->_left) + 1;int righthigh = treeleafhigh(root->_right) + 1;if (lefthigh > righthigh){return lefthigh;}else{return righthigh;}
}

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

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

相关文章

618快到了,送大家一款自动化脚本工具,一起薅羊毛

前言 一年一次的618活动来了&#xff0c;大家做好准备了&#xff0c;奇谈君为大家准备好用的618神器&#xff0c;解放双手&#xff0c;简单操作就可以把红包拿到手。 京淘自动助手 首次使用前需要进行设置 将手机的无障碍权限和悬浮窗权限打开 设置完成后&#xff0c;可以把…

什么是健康信息卡

健康档案信息卡是交由居民本人保管的个人健康信息卡片。 其内容包括&#xff1a;居民个人主要基本信息、健康档案编码、患有的重要疾病、过敏史以及紧急情况下的联系人及联系方式&#xff0c;还有所属基层医疗机构的责任医生、护士及联系电话等。它主要用于居民在复诊、转诊或接…

UTC与GPS时间转换-[week, sow]

UTC与GPS时间转换-[week, sow] utc2gpsgps2utc测试参考 Ref: Global Positioning System utc2gps matlab源码 function res utc2gps(utc_t, weekStart)%% parameterssec_day 86400;sec_week 604800;leapsec 18; % 默认周一为一周的开始if nargin < 2weekStart d…

算法打卡 Day10(栈与队列)-用栈实现队列 + 用队列实现栈

今天开始进入栈与队列啦&#xff01; 文章目录 栈与队列理论基础栈 Leetcode 232-用栈实现队列题目描述解题思路 Leetcode 225-用队列实现栈题目描述解题思路 首先我们来学习一下栈与队列的基础知识~ 栈与队列理论基础 栈与队列的区别是&#xff1a;栈是先进后出&#xff0c…

Python | Leetcode Python题解之第111题二叉树的最小深度

题目&#xff1a; 题解&#xff1a; class Solution:def minDepth(self, root: TreeNode) -> int:if not root:return 0que collections.deque([(root, 1)])while que:node, depth que.popleft()if not node.left and not node.right:return depthif node.left:que.appen…

cnVcXsrv 21.1.13.1—VcXsrv 21.1.13中文版本简单说明~~

对于VcXsrv的使用目的和用途相信大家都很了解。前不久VcXsrv做了更新&#xff0c;并且将项目托管到github上了。链接如下&#xff1a; VcXsrv: Windows X-server based on the xorg git sourceshttps://github.com/marchaesen/vcxsrv也可以简单查看如下链接&#xff1a; VcXs…

在matlab里面计算一组给定参数的方程的解

如&#xff1a; k (1:1024); f (x)(1-x-k.*x.^2); 在这段代码给出了一组函数&#xff0c;若需要计算f0&#xff0c;可以通过自带的函数实现&#xff1a; x0 zeros(length(k),1); options optimoptions(fsolve,Display,none,TolX,tol,TolFun,tol); tic for ik 1:length…

全网讲的最详细的Docker镜像分层存储原理

先说结论&#xff0c;容器镜像分层存储图示 欢迎关注 实验环境准备 当前实验docker版本24.0.7如下&#xff0c;当前docker版本使用overlay2机制存储镜像 Client: Docker Engine - CommunityVersion: 24.0.7API version: 1.43Go version: go1.20.10…

Three.js 研究:2、如何让动画线性运动

1、默认的动画含有加速度并非线性的 制作好的动画很明显是非线性的&#xff0c;这是一个运动环&#xff0c;为了让环运行线性进行如下设置。 2、设置动画成为线性动画

Vue从入门到实战Day07

一、vuex概述 目标&#xff1a;明确vuex是什么&#xff0c;应用场景&#xff0c;优势 1. 是什么&#xff1a; vuex是一个vue的状态管理工具&#xff0c;状态就是数据。 大白话&#xff1a;vuex是一个插件&#xff0c;可以帮助我们管理vue通用的数据&#xff08;多组件共享的…

解锁数据关联之道:SQL 表连接详解

文章目录 概述表关系横向连接内连接 inner join左连接 left join右连接 right join全连接 full join交叉连接 cross join 纵向合并UNION ALLUNION 概述 在数据处理、数据分析中常会用到表连接。表连接的作用是将多个表中的数据关联起来&#xff0c;以便在查询过程中获取更全面…

家政项目day2 需求分析(模拟入职后熟悉业务流程)

目录 1 项目主体介绍1.1 项目背景1.2 运营模式1.3 项目业务流程 2 运营端需求2.1 服务类型管理2.2 服务项目&#xff08;服务&#xff09;管理2.3 区域管理2.4 区域服务管理2.5 相关数据库表的管理2.6 设计工程结构2.7 测试接口&#xff08;接口断点查看业务代码&#xff09; 1…

【机器学习与大模型】开源大模型和闭源大模型:技术发展与社会责任的平衡点

目录 &#x1f4a1;引言✈️✈️一&#xff0c;开源大模型的优势与劣势✈️✈️1.1 优势&#xff1a;✈️✈️1.2 挑战和劣势&#xff1a; &#x1f680;&#x1f680;2. 闭源大模型的优势与劣势&#x1f680;&#x1f680;2.1 优势&#xff1a;&#x1f680;&#x1f680;2.2 …

【pyspark速成专家】7_SparkSQL编程1

目录 一&#xff0c;RDD&#xff0c;DataFrame和DataSet对比 二&#xff0c;创建DataFrame 本节将介绍SparkSQL编程基本概念和基本用法。 不同于RDD编程的命令式编程范式&#xff0c;SparkSQL编程是一种声明式编程范式&#xff0c;我们可以通过SQL语句或者调用DataFrame的相…

amis 联动效果触发的几种方式

联动效果实现主要俩种方式: 1.表达式实现联动,基于组件内或数据链的变量变化的联动 比如&#xff1a; "source": "/amis/api/mock2/options/level2?name${name} " (必须是这种字符串拼接形式,在data数据映射中表达式不会触发联动) 所有初始化接口链…

Java进阶学习笔记10——子类构造器

子类构造器的特点&#xff1a; 子类的全部构造器&#xff0c;都会先调用父类的构造器&#xff0c;再执行自己。 子类会继承父类的数据&#xff0c;可能还会使用父类的数据。所以&#xff0c;子类初始化之前&#xff0c;一定先要完成父类数据的初始化&#xff0c;原因在于&…

线程生命周期

创建线程的两种方法 1.继承Thread类 2.实现Runnable接口 线程从创建到消亡分为新建、就绪、运行、阻塞、死亡5种状态。 新建状态 创建一个线程就处于新建状态。此时线程对象已经被分配了内存空间&#xff0c;并且私有数据也被初始化&#xff0c;但是该线程还不能运行。 就…

03-02-Vue组件之间的传值

前言 我们接着上一篇文章 03-01-Vue组件的定义和注册 来讲。 下一篇文章 04-Vue&#xff1a;ref获取页面节点–很简单 父组件向子组件传值 我们可以这样理解&#xff1a;Vue实例就是一个父组件&#xff0c;而我们自定义的组件&#xff08;包括全局组件、私有组件&#xff09;…

足球走地全自动化操作软件实现过程

本次采用selenium实现自动化操作的流程 打开浏览器录入账号密码等待数据请求&#xff08;监听&#xff09;有新数据&#xff0c;进行自动化操作通过homeName搜索&#xff0c;找到对应数据找到对应的类型&#xff08;让、大小…&#xff09;找到对应的盘口输入数量提交 附登录…

Python语法(全)

前言&#xff1a; 下面是Python基本的语法&#xff0c;大家耐心观看&#xff01; 1.基础语法 1.1字面量 字面量&#xff1a;在代码中&#xff0c;被写下来的的固定的值&#xff0c;称之为字面 1.2字符串 字符串&#xff08;string&#xff09;&#xff0c;又称文本&#xff…