【数据结构】二叉树-堆(下)-链式二叉树

news2024/12/23 22:54:41

在这里插入图片描述
个人主页~

二叉树-堆(上)
栈和队列


二叉树

  • 四、堆的代码实现
    • Heap.h
    • Heap.c
    • test.c
  • 五、堆的应用
    • 堆排序思想进行排序
  • 六、二叉树链式结构的实现
    • BTree.h
    • BTree.c
    • test.c

四、堆的代码实现

Heap.h

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int HPDataType;

typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}Heap;
// 堆的初始化
void HeapInit(Heap* hp);
// 堆的销毁
void HeapDestory(Heap* hp);
// 堆的插入
void HeapPush(Heap* hp, HPDataType x);
// 堆的删除
void HeapPop(Heap* hp);
// 取堆顶的数据
HPDataType HeapTop(Heap* hp);
// 堆的数据个数
int HeapSize(Heap* hp);
// 堆的判空
int HeapEmpty(Heap* hp);
void AdjustUp(HPDataType* a, int child); 
//向下调整算法
void AdjustDown(HPDataType* a, int n, int parent);

Heap.c

#include "Heap.h"

void Swap(HPDataType* n1, HPDataType* n2)
{
	HPDataType* tmp = *n1;
	*n1 = *n2;
	*n2 = tmp;
}

void HeapInit(Heap* hp)
{
	assert(hp);
	hp->a = NULL;
	hp->capacity = hp->size = 0;
}

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

void HeapPush(Heap* hp, HPDataType x)
{
	assert(hp);
	if(hp->capacity == hp->size)
	{
		int newcapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;
		HPDataType* tmp = (HPDataType*)realloc(hp->a, newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		hp->a = tmp;
		hp->capacity = newcapacity;
	}
	hp->a[hp->size] = x;
	hp->size++;
	AdjustUp(hp->a, hp->size - 1);
}

void HeapPop(Heap* hp)
{
	assert(hp);
	assert(!HeapEmpty(hp));
	Swap(&hp->a[0], &hp->a[hp->size - 1]);
	hp->size--;
	AdjustDown(hp->a, hp->size, 0);
}

HPDataType HeapTop(Heap* hp)
{
	assert(hp);
	assert(!HeapEmpty(hp));
	return hp->a[0];
}

int HeapSize(Heap* hp)
{
	assert(hp);
	return hp->size;
}

int HeapEmpty(Heap* hp)
{
	assert(hp);
	return hp->size == 0;
}

void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	//while (parent >= 0)
	while (child > 0)
	{
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

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++;
		}

		if (a[child] > a[parent])
		{
			Swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

test.c

#include "Heap.h"

int main()
{
	Heap h;
	HeapInit(&h);
	HeapPush(&h, 1);
	HeapPush(&h, 4);
	HeapPush(&h, 7);
	HeapPush(&h, 2);
	HeapPush(&h, 5);
	HeapPush(&h, 9);
	printf("%d\n", HeapTop(&h));

	HeapPop(&h);
	printf("%d", HeapTop(&h));

	HeapDestory(&h);
	return 0;
}

在这里插入图片描述

五、堆的应用

堆排序思想进行排序

我们在上面实现了堆,如果想要升序数组就建大堆,降序数组就建小堆
但建堆并不意味着建完就可以了,想要升序/降序数组的话,建完大堆/小堆后用向下调整算法将堆调整成小堆/大堆,这样调整出来的堆就是一个升序/降序数组

在排序当中,堆排序是一种时间复杂度较低的排序,要远优于冒泡排序,在使用堆排序时,要使用向下调整算法,这样我们就可以最大限度的减少时间的使用

在堆排序中有一个很经典的问题就是TopK问题,即一堆数据,个数为n(n>>k),求这堆数据中最大/最小的k个数据
如果是求前k个最大的元素,则用前k个元素建小堆
如果是求前k个最小的元素,则用前k个元素建大堆
然后再用剩下的n-k个元素一次与堆顶元素来比较,不满足则替换堆顶元素
也就是说,我们用求前k个最大数据来举例,我们先将整组数据的前k个元素建一个小堆,小堆的根是整个堆里最小的,用它来和剩余的n-k个元素比较,如果剩余的元素中的某一个比小堆根大,那么就替换掉,再用向下调整算法调整,这样一来,最大的数据都沉底了,堆中最小的数据继续与剩余的数据比较,重复上述步骤,当所有剩余元素都比完了之后,剩下的这个小堆就是前k个最大数

六、二叉树链式结构的实现

BTree.h

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef char BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int* pi);
// 二叉树销毁
void BinaryTreeDestory(BTNode* root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);

BTree.c

#define _CRT_SECURE_NO_WARNINGS

#include "BTree.h"

BTNode* BuyNode(BTDataType x)
{
	BTNode* new = (BTNode*)malloc(sizeof(BTNode));
	if (new == NULL)
	{
		perror("malloc fail");
		return NULL;
	}

	new->data = x;
	new->left =  NULL;
	new->right = NULL;

	return new;
}

BTNode* BinaryTreeCreate(BTDataType* a,int n, int* pi) 
{
    if (*pi >= n || a[*pi] == '#')
	{ 
		// 如果到达数组末尾或遇到#,则返回NULL  
        (*pi)++;
        return NULL;
    }

	BTNode* node = BuyNode(a[*pi]);
    (*pi)++; // 移动到下一个节点  

    node->left = BinaryTreeCreate(a, n, pi); // 递归创建左子树  
    node->right = BinaryTreeCreate(a, n, pi); // 递归创建右子树  

    return node;
}

void BinaryTreeDestory(BTNode* root)
{
	if (root == NULL)
		return;
	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	free(root);
}

int BinaryTreeSize(BTNode* root)
{
	//return root == NULL ? 0 : BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
	if (root == NULL)
		return 0;
	return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

int BinaryTreeLeafSize(BTNode* root)
{
	if (root == NULL)
		return 0;
	if (root->left == NULL && root->right == NULL)
		return 1;
	return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

int BinaryTreeLevelKSize(BTNode* root, int k)
{
	assert(k > 0);
	if (root == NULL)
		return 0;
	if (k == 1)
		return 1;
	return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;
	if (root->data = x)
		return root;
	BTNode* ret1 = BinaryTreeFind(root->left, x);

	if (ret1)
		return ret1;

	BTNode* ret2 = BinaryTreeFind(root->right, x);

	if (ret2)
		return ret2;

	return NULL;
}

void BinaryTreePrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	printf("%c ", root->data);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);

}

void BinaryTreeInOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	BinaryTreeInOrder(root->left);
	printf("%c ", root->data);
	BinaryTreeInOrder(root->right);

}

void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	BinaryTreeInOrder(root->left);
	BinaryTreeInOrder(root->right);
	printf("%c ", root->data);

}

test.c

#define _CRT_SECURE_NO_WARNINGS

#include "BTree.h"


int main()
{
	int i = 0;
	BTDataType val[] = { "ABD##E#H##CF##G##" };

	BTNode* tree = BinaryTreeCreate(val, 17, &i);
	BinaryTreePrevOrder(tree);
	printf("\n");
	BinaryTreeInOrder(tree);
	printf("\n");
	BinaryTreePostOrder(tree);
	printf("\n");
	
	printf("%d\n", BinaryTreeSize(tree));

	printf("%d\n", BinaryTreeLeafSize(tree));

	printf("%d\n", BinaryTreeLevelKSize(tree,3));


	BinaryTreeDestory(tree);
	return 0;
}

在这里插入图片描述


下一篇我们来详细剖析链式二叉树的实现~
在这里插入图片描述

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

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

相关文章

现在,所有人都能免费用GPT-4o了!

OpenAI今日官宣&#xff0c;ChatGPT正式向所有用户免费开放&#xff01;所有用户均可以访问定制化GPT、分析图表、询问有关照片的问题以及5月初GPT-4o添加的其他功能。 OpenAI今天在X上发布推文&#xff1a; 「所有ChatGPT免费用户现在都可以使用浏览、视觉、数据分析、文件上…

【动态规划 组合数学 放球问题】2338. 统计理想数组的数目

本文涉及知识点 动态规划汇总 组合数学汇总 【组合数学 隔板法 容斥原理】放球问题 本题同解 【动态规划】【前缀和】【分组】2338. 统计理想数组的数目 LeetCode2338. 统计理想数组的数目 给你两个整数 n 和 maxValue &#xff0c;用于描述一个 理想数组 。 对于下标从 0…

在“AI PC”中使用NPU运行 Phi-3-mini

欢迎关注我的公众号“ONE生产力”&#xff0c;获取更多AI、云计算资讯分享&#xff01; 前段时间&#xff0c;我做了一系列微软Phi-3-mini小语言模型的教程&#xff0c;很多朋友参考教程进行了实践&#xff0c;其中有一个朋友反馈说模型token推理很慢&#xff0c;没有答道我说…

做项目时,怎么运用 SWOT 分析法进行项目或决策分析?

SWOT分析法是一种常用的战略工具&#xff0c;用于评估项目或决策的优势、劣势、机会和威胁。以下是在项目或决策分析中如何运用SWOT分析法的一般步骤&#xff1a; 步骤1&#xff1a;明确分析的目标 在进行SWOT分析之前&#xff0c;首先要明确分析的目标是什么。你可能想要分析…

如何学习ai agent?

如何学习Agent&#xff0c;推荐阅读《动手做AI Agent》这本书。 推荐理由&#xff1a; 1&#xff1a;一本书能够全方位了解并探索Agent的奥秘&#xff01; &#xff08;1&#xff09;Agent的发展进程。 &#xff08;2&#xff09;可以帮我们做哪些事&#xff1a;自动办公&am…

Mysql基础教程(10):LIMIT

MySQL LIMIT 用法与实例 在 MySQL 中&#xff0c;我们使用 LIMIT 子句来限定 SELECT 语句返回的行的数量。 MySQL LIMIT语法 该 LIMIT 子句可用于限制 SELECT 语句返回的行数。 LIMIT 接受一个或两个非负数正数作为参数。 LIMIT 子句的语法如下&#xff1a; LIMIT [offset,…

python绘制北京汽车流量热力图:从原理到实践

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言 二、热力图绘制原理 三、热力图绘制实践 1. 数据准备 2. 地图组件选择 3. 数据…

seRsync + Rsync 实时同步

文章目录 1&#xff0c;结构图2&#xff0c;节点A2.1 安装rsync2.2 安装seRsync2.3&#xff0c; 创建seRsync的守护进程用systemd管理并启动2.4&#xff0c;上传rsync.pass密码文件到配置文件目录&#xff1a;/etc/2.5 &#xff0c;重新加载systemd&#xff0c;启动sersyncd守护…

CSPM.pdf

PDF转图片 归档&#xff1a;

直播领域新宠—第三代大模型无人直播系统:提升销售业绩的秘密武器

随着科技的飞速发展和人们对智能化生活的追求&#xff0c;直播领域也迎来了革新性的突破。第三代大模型无人直播系统&#xff0c;作为直播领域的新宠&#xff0c;正以其独特的魅力和优势&#xff0c;成为提升销售业绩的秘密武器。 首先&#xff0c;第三代大模型无人直播系统具…

3---C++之list(逻辑梳理、简单使用演示、部分源码实现)

一、先决知识点1——认识list&#xff1a; list底层实现是双向链表&#xff0c;但是不是循环链表。list是否使用哨兵节点&#xff0c;是细节问题&#xff0c;C标准并未规定。list是链表&#xff0c;他的优势在于对节点的操作会十分灵活&#xff0c;因此它在需要频繁插入和删除元…

压力测试JMeter

压力测试JMeter 1 下载JMeter1.1 测试计划1.2 JMeter Address Already in use 错误解决1.3 java 内存模型1.4 jconsole与jvisualvm1.5 优化方向1.6 Nginx动静分离 1 下载JMeter 官网地址&#xff1a;https://jmeter.apache.org/download_jmeter.cgi 运行apache-jmeter-5.6.3\…

鸿蒙应用Stage模型【应用/组件级配置】

应用/组件级配置 在开发应用时&#xff0c;需要配置应用的一些标签&#xff0c;例如应用的包名、图标等标识特征的属性。本文描述了在开发应用需要配置的一些关键标签。 应用包名配置 应用需要在工程的AppScope目录下的[app.json5配置文件]中配置bundleName标签&#xff0c;…

万字长文详解QUIC协议,为什么有了TCP我们还需要QUIC?

本文目录 1.前言2. HTTP缺点缺点一&#xff1a;建立连接的握手延迟大缺点二&#xff1a;多路复用的队首阻塞缺点三&#xff1a;TCP协议的更新滞后 3.TCP缺点3.QUIC优点一&#xff1a;避免队首阻塞的多路复用优点二&#xff1a;支持连接迁移优点三&#xff1a;可插拔的拥塞控制优…

YAML快速编写示例

一、案例 1.1 自主式创建service关联上方的pod 资源名称my-nginx-kkk命名空间my-kkk容器镜像nginx:1.21容器端口80标签njzb:my-kkk 1.1.1 创建一个demo文件夹 1.1.2 创建并获取模版文件 1.1.3 查看服务并编写yaml文件 1.1.4 编写yaml文件并部署&#xff0c;查看服务是否运行成…

Kotlin和Swift的前世一定是兄弟

Swift介绍 Swift这门编程语言主要用于iOS和MacOS的开发&#xff0c;可以说是非常流行的一门编程语言&#xff0c;我只想说&#xff0c;如果你会Kotlin&#xff0c;那么你学习Swift会非常容易&#xff0c;反之亦然。下载XCode&#xff0c;然后你就可以创建Playground练习Swift语…

Qt图像处理技术十:得到QImage图像的高斯模糊

效果图 参数为5 参数为20 原理 高斯模糊使用正态分布来分配周围像素的权重。具体来说&#xff0c;距离中心点越近的像素对最终结果的影响越大&#xff0c;权重也越高&#xff1b;随着距离的增加&#xff0c;权重逐渐减小。 这种权重分配方式确保了图像在模糊处理时&#xff0…

Docker(Centos7+)

先确定是否 Centos 7 及以上的版本 查看是否 ping 通外网 linux centos7运行下面的代码&#xff0c;基本上都可以正常安装 # 删除之前的docker残留 yum -y remove docker*yum install -y yum-utilsyum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/…

中草药识别系统Python+深度学习人工智能+TensorFlow+卷积神经网络算法模型

一、介绍 中草药识别系统。本系统基于TensorFlow搭建卷积神经网络算法&#xff08;ResNet50算法&#xff09;通过对10中常见的中草药图片数据集&#xff08;‘丹参’, ‘五味子’, ‘山茱萸’, ‘柴胡’, ‘桔梗’, ‘牡丹皮’, ‘连翘’, ‘金银花’, ‘黄姜’, ‘黄芩’&…

我给线程池管理框架hippo4j找bug

1 虚拟机参数不生效 hippo4j的docker启动脚本位于 docker/docker-startup.sh 。从下图可以看到 JAVA_OPT放在了jar包名 hippo4j-server.jar之后&#xff0c;而只有项目参数才放在jar包名之后。 实际上这里JAVA_OPT中包含虚拟机参数&#xff0c;而虚拟机参数要放在jar包名之前…