数据结构之四:堆和二叉树
堆的实现:SData/Heap/heap.c · Hera_Yc/bit_C_学习 - 码云 - 开源中国
树
树的概念
树:是一个非线性数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。
把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
- 有一个特殊的结点,称为根结点,根节点没有前驱结点。
- 除根节点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1<= i<= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继
- 因此,树是递归定义的。
树形结构中,子树之间不能有交集,否则就不是树形结构。
(树中不能构成回路,不能有孤立的点)。
如何理解树是递归定义的呢?
相关概念
树的结构定义
链式表示:
数组表示:
二叉树
二叉树概念
一棵二叉树是结点的一个有限集合,该集合:
- 或者为空。
- 由一个根节点加上两棵别称为左子树和右子树的二叉树组成。
- 二叉树不存在度大于2的结点。
- 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树。
特殊的二叉树
- 满二叉树:一个二叉树,如果每一个层的结点数都达到最大值(2),则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K。那么,结点总数是(2^K - 1),则它就是满二叉树。
- 完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。满二叉树是一种特殊的完全二叉树。(假设有k层的完全二叉树,前k-1层都是满的,最后一层可以不满,但必须是从左到右连续)。
二叉树性质
1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)个结点。
2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是2^h -1。
3. 对任何一棵二叉树, 如果度为0其叶结点个数为n0 , 度为2的分支结点个数为n2 ,则有n0=n2+1。
即:度为0(叶子结点)的数量 = 度为2的结点数量 + 1 。
3.在具有 2n 个结点的完全二叉树中,叶子结点个数为( )
A n
B n+1
C n-1
D n/2解析:假设叶子结点右x个,则度为2的结点右x-1个
总节点数 = x + (x - 1) + 度为1的结点数量
所以:总数量= 2*n =x+(x-1)+1 = > x=n
4.二叉树的高度:(用于堆的选树、搜索二叉树、平衡搜索二叉树)
二叉树存储
二叉树的逻辑结构是一棵树,物理结构分为顺序存储和链式存储两种结构。
数组实现:
------------------------------------------------二叉树实现在文章末尾 ------------------------------------------------
堆
堆:实际上就是数组形式存储的完全二叉树。(逻辑结构是完全二叉树,物理结构是数组)
堆的作用:堆排序效率高、选数等
向下调整算法
(向下调整算法是堆中最重要的算法,堆、堆排序等都需要调整算法来支撑。
向下调整算法构建堆:
前提是:根节点的左右字数必须是大堆或者小堆。
//向下调整算法
//左右子树必须保证:都是小堆(或者大堆)
static void AdjustDown(HPDataType* a, int n, int root)
{int parent = root;int child = parent * 2 + 1;//默认是左孩子更小while (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;}}
}
数组建堆
向下调整算法用于建堆
//arr是传入的数据 arr[n]
void HeapInit(Heap* php, HPDataType* arr, int n)
{assert(php);php->_a = (HPDataType*)malloc(sizeof(HPDataType) * n);if (php->_a == NULL){printf("%s\n", strerror(errno));return;}memcpy(php->_a, arr, sizeof(HPDataType) * n);//内存拷贝php->_size = n;php->_capacity = n;//数组建堆//利用的向下调整算法:// 从最下面的第一个非叶子结点开始调整,// 一层层完成小堆的构建//直到根节点,在对根节点向下调整int i = 0;for (i=(php->_size-1);i >= 0; i--){AdjustDown(php->_a, php->_size, i);}//
}
向上调整算法
向上调整算法用于入堆。
向上调整算法与向下调整类似,不过是从子节点往父节点走。对于堆而言,父节点和子节点的下标关系是必须掌握的。
void AdjustUp(HPDataType* arr,int n,int child)
{//从子节点往父结点调整//由child得出parentint 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;}}
}
堆排序:见排序与查找-CSDN博客。
入堆
void HeapPush(Heap* php, HPDataType x)
{assert(php);if (php->_size == php->_capacity){php->_capacity *= 2;HPDataType* tmp = (HPDataType*)realloc(php->_a,sizeof(HPDataType) * (php->_size));if (tmp == NULL){printf("%s\n", strerror(errno));return;}php->_a = tmp;}php->_a[php->_size++] = x;AdjustUp(php->_a, php->_size, php->_size-1);}
与堆有关的OJ题:面试题 17.14. 最小K个数 - 力扣(LeetCode)(典型的TopK问题)
N个树中找出最大或最小的前K个数?
- 排序 问题:a、N*logN的效率能否进一步提高? b、假设N非常大,内存不够排序
- 建一个大小为K的堆来解决问题,
eg:找最大的前K个,建一个大小为K的小堆,比堆顶大则进堆(顶替掉堆顶的数据,然后向下调整)。
- 大堆性质:堆顶的元素一定是最大的。(找最小的K个数)。
- 小堆性质:堆顶的元素一定是最小的。(找最大的K个数)。
解法一在:leetcode/TopK/test_1.c · Hera_Yc/bit_C_学习 - 码云 - 开源中国
//建K大小的堆解法
void Swap(int* x, int* y) {int tmp = *x;*x = *y;*y = tmp;
}void AdjustDown(int* arr, int n, int root) {int parent = root;int child = parent * 2 + 1;while (child < n) // child不越界{if (child + 1 < n && arr[child + 1] > arr[child]) // 大堆找更大的孩子{child++;}if (arr[child] > arr[parent]) // 大堆的父节点更大{Swap(&arr[child], &arr[parent]);parent = child;child = 2 * parent + 1; // 向下迭代} else {break;}}
}int* smallestK(int* arr, int arrSize, int k, int* returnSize) {*returnSize = k;if (k == 0)return NULL;int* retArr = (int*)malloc(sizeof(int) * k);*returnSize = k;int i = 0;// 建K个数的大堆:for (i = 0; i < k; i++) {retArr[i] = arr[i];}for (i = (k - 1 - 1) / 2; i >= 0; i--) {AdjustDown(retArr, k, i);} // 大堆建立完成:K个数的大堆int j = 0;for (j = k; j < arrSize; j++) {if (arr[j] < retArr[0]) {retArr[0] = arr[j];AdjustDown(retArr, k, 0);}}return retArr;
}
------------------------------------------------堆到此结束 ------------------------------------------------
二叉树
伪树
在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在对二叉树结构掌握还不够深入,为了降低学习成本,此处手动快速创建一棵简单的二叉树,快速进入二叉树操作学习,等二叉树结构了解的差不多时,我们反过头再来研究二叉树真正的创建方式。
BTNode* BuyNode(BTDataType ch)
{BTNode* node = (BTNode*)malloc(sizeof(BTNode));node->_data = ch;node->_left = NULL;node->_right = NULL;return node;
}
//一个树的增删查改没有意义
//这里写一颗伪树
BTNode* A = BuyNode('A');
BTNode* B = BuyNode('B');
BTNode* C = BuyNode('C');
BTNode* D = BuyNode('D');
BTNode* E = BuyNode('E');
BTNode* f = BuyNode('f');
A->_left = B;
A->_right = C;
B->_left = D;
B->_right = E;
D->_left = f;
(学习二叉树的目的是为了掌握更加深层的数据结构,因此会边学边补充)
任何一个二叉树,都要看作三个部分:
1、根节点。2、左子树。3、右子树。
遍历
- 深度优先遍历:先往深处走,无路可走是退回来 访问其他结点。(递归和栈实现)。
- 广度优先遍历:一层层的走,走完一层走下一层。(队列实现)。
树不同于其他的数据结构:
- 简单的树的增删查改没有意义。
- 单独的二叉树没有意义。
- 平衡二叉树和搜索二叉树才有实际意义。
深度优先遍历
// 二叉树前序遍历
void PreOrder(BTNode* root);
// 二叉树中序遍历
void InOrder(BTNode* root);
// 二叉树后序遍历
void PostOrder(BTNode* root);
typedef char BTDataType;
typedef struct BinaryTree
{BTDataType _data;struct BinaryTree* _left;struct BinaryTree* _right;
}BTNode;
//前序
void PreOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}printf("%c ", root->_data); //根PreOrder(root->_left); //左子树PreOrder(root->_right); //右子树
}
int TreeSize(BTNode* root)
{if (root == NULL)return 0;elsereturn 1 + TreeSize(root->_left) + TreeSize(root->_right);
}
关于TreeSize如何返回值?
广度优先遍历
广度优先遍历:即层序遍历,与递归无关,通过队列的性质(先进先出)来实现。
结点个数
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
实现
int BinaryTreeSize(BTNode* root)
{if (root == NULL)return 0;elsereturn 1 + TreeSize(root->_left) + TreeSize(root->_right);
}
int BinaryTreeLeafSize(BTNode* root)
{if (root == NULL){return 0;}else if(root->_left == NULL && root->_right == NULL){return 1;}else{return TreeLeafSize(root->_left) + TreeLeafSize(root->_right);}
}
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{if (root == NULL)return 0;if (k == 1){return 1;}return BinaryTreeLevelKSize(root->_left, k - 1)+ BinaryTreeLevelKSize(root->_right, k - 1);
}
查找
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL)return NULL;if (root->_data == x)return root;BTNode* node = BinaryTreeFind(root->_left, x);if (node)return node;node = BinaryTreeFind(root->_right, x);if (node)return node;return NULL;
}
销毁
// 二叉树销毁
void BinaryTreeDestory(BTNode* root);
// 二叉树销毁
void BinaryTreeDestory(BTNode* root)
{if (root == NULL)return;BinaryTreeDestory(root->_left);BinaryTreeDestory(root->_right);free((root));//后序free不需要保存左和右root = NULL;
}
判断一棵树是否是完全二叉树
// 判断二叉树是否是完全二叉树
//是返回1,不是返回0
int BinaryTreeComplete(BTNode* root)
{//完全二叉树的层序遍历是两段:非空结点+空节点Queue q;QueueInit(&q);if (root == NULL)return 0;QueuePush(&q, root);while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);if (front == NULL){break;}QueuePush(&q, front->_left);QueuePush(&q, front->_right);}while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);if (front){QueueDestory(&q);return 0;}}QueueDestory(&q);return 1;
}
------------------------------------------本文二叉树到此结束-----------------------------------------------
到这里,二叉树的学习进程仅有40%左右,其余待补充.....
相关文章:

数据结构之四:堆和二叉树
堆的实现:SData/Heap/heap.c Hera_Yc/bit_C_学习 - 码云 - 开源中国 树 树的概念 树:是一个非线性数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。 把它叫做树是因为它看起来像一棵倒挂的树,也就…...
【论文阅读】国际开源发展经验及其对我国开源创新体系建设的启示
作者:包云岗老师 包云岗老师是计算机体系结构方向的大牛,推动了体系结构方面的开源事业! 欢迎对本栏目感兴趣的人学习"一生一芯"~ 学习体会: 承接前文,唐志敏老师讲到已有的软硬件生态系统和开发成本制约了对新结构的探…...
redis击穿,穿透,雪崩以及解决方案
目录 击穿 解决方案一 解决方案二 穿透 解决方案 雪崩 解决方案 击穿 指的是单个key在缓存中查不到,去数据库查询,这样如果并发不大或者数据库数据量不大的话是没有什么问题的。 如果数据库数据量大并且是高并发的情况下那么就可能会造成数据库压…...

时频转换 | Matlab格拉姆角和场Gramian angular summation field一维数据转二维图像方法
目录 基本介绍程序设计参考资料获取方式 基本介绍 时频转换 | Matlab格拉姆角和场Gramian angular summation field一维数据转二维图像方法 程序设计 clear clc % close all load x.mat % 导入数据 x x(1:5120); % 本数据只选择5120个点进行分析 fs 6400 ; % 数据采样频…...

qt QCryptographicHash详解
1、概述 QCryptographicHash是Qt框架中提供的一个类,用于实现加密散列函数,即哈希函数。哈希函数能够将任意长度的数据转换为固定长度的哈希值,也称为散列值或数据指纹。这个哈希值通常用于数据的完整性校验、密码存储等场景。QCryptographi…...

亚马逊云科技大语言模型加速OCR应用场景发展
目录 前言Amazon Bedrock关于OCR解决方案Amazon Bedrock进行OCR关键信息提取方案注册亚马逊账号API调用环境搭建 总结 前言 大语言模型是一种基于神经网络的自然语言处理技术,它能够学习和预测自然语言文本中的规律和模式,可以理解和生成自然语言的人工…...

什么是分库?分表?分库分表?
分库分表,是企业里面比较常见的针对高并发、数据量大的场景下的一种技术优化方案,所谓“分库分表”,根本不是一回事,而是三件事,他们要解决的问题也都不一样。 这三个事分别是“只分库不分表”、“只分表不分库”、以…...

QT 中 sqlite 数据库使用
一、前提 --pro文件添加sql模块QT core gui sql二、使用 说明 --用于与数据库建立连接QSqlDatabase--执行各种sql语句QSqlQuery--提供数据库特定的错误信息QSqlError查看qt支持的驱动 QStringList list QSqlDatabase::drivers();qDebug()<<list;连接 sqlite3 数据库 …...

不一样的CSS(4)--icon图标系列之svg
序言 上一节内容我们讲解了如何利用css去画一个五角星,其中包括了使用svg的方法,有些小伙伴们对svg的使用不是很了解,那么本节内容我们主要来讲一下,关于svg标签的的使用。 目录 序言一、svg的介绍二、安装SVG扩展插件三、SVG基…...

Level DB --- Cache
class Cache是Level DB中的重要的数据结构,它是一个LRU(Least Recently Used) Cache的实现。这里面的判断条件主要是内存大小(而不是存储entry的个数)。当内存达到上界,会释放不被使用的entry(存…...

学在西电录播课使用python下载,通过解析m3u8协议、多线程下载ts视频块以及ffmpeg合并
本文涵盖的内容仅供个人学习使用,如果侵犯学校权利,麻烦联系我删除。 初衷 研究生必修选逃, 期末复习怕漏过重点题目,但是看学在西电的录播回放课一卡一卡的,于是想在空余时间一个个下载下来,然后到时候就…...

Springboot3介绍
一、Springboot3简介: https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started.html?spmwolai.workspace.0.0.68b62306Q6jtTw#getting-started.introducing-spring-boot 无论使用XML、注解、Java配置类还是他们的混合用法,配置文件过于…...
Oracle 11G DataGuard GAP 修复过程(通过主库scn增备恢复)
Oracle 11G DataGuard GAP 修复 (通过主库scn增备恢复) 介绍 DG GAP 顾名思义就是:DG不同步,当备库不能接受到一个或多个主库的归档日志文件时候,就发生了 GAP。 那么,如果遇到GAP如何修复呢?…...

WLAN AutoConfig服务假死?重启服务恢复网络连接!
目录 背景: 过程: 可能引起原因: 具体解决步骤: 方法一: 方法二: 总结: 背景: 这个问题困扰我好长一段时间了,每次下班将电脑关机后,次日早上电脑开机…...
【linux】(30)shell-条件判断
if 语句 if 语句是 Shell 脚本中用于条件判断的基本结构。 基本语法 if 语句的基本语法如下: if [ condition ] thencommands ficondition 是要测试的条件。commands 是在条件为真时要执行的命令。 示例 简单条件判断 #!/bin/bashif [ 1 -eq 1 ] thenecho &q…...

docker安装启动问题解决排查
一、安装docker报错 刚开始安装docker报这个错: Error: Transaction test error: file /usr/libexec/docker/cli-plugins/docker-buildx from install of docker-ce-cli-1:20.10.8-3.el8.x86_64 conflicts with file from package docker-buildx-plugin-0:0.14.0…...
《MySQL 查询进阶:复杂查询语句的魅力》
一、引言 MySQL 的复杂查询语句就像是一把神奇的钥匙,能够打开数据世界的大门,展现出数据的无限魅力。本文将带你深入探索 MySQL 查询进阶技巧,从常用查询到子查询,再到视图的运用,让你领略复杂查询语句的强大功能。 …...

OpenHarmony-3.HDF框架(2)
OpenHarmony HDF 平台驱动 1.平台驱动概述 系统平台驱动框架是系统驱动框架的重要组成部分,它基于HDF驱动框架、操作系统适配层(OSAL, operating system abstraction layer)以及驱动配置管理机制,为各类平台设备驱动的实现提供标准模型。 系统平台驱动(…...

人大金仓(KingBaseEs)数据库操作手册
人大金仓数据库(KingbaseES)是由北京人大金仓信息技术股份有限公司(简称人大金仓)自主研发的、具有自主知识产权的通用关系型数据库管理系统。 官方下载地址:KingbaseES 人大金仓数据库 KES技术文档在线手册…...

Flink+Paimon实时数据湖仓实践分享
随着 Paimon 近两年的推广普及,使用 FlinkPaimon 构建数据湖仓的实践也越来越多。在 Flink 实时数据开发中,对于依赖大量状态 state 的场景,如长周期的累加指标计算、回撤长历史数据并更新等,使用实时数仓作为中间存储来代替 Flin…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...