C语言实现数据结构:堆排序和二叉树_链式

在这里插入图片描述


一.堆的应用

1.堆排序

void test01()
{int arr[] = { 17,20,10,13,19,15 };int n = sizeof(arr) / sizeof(arr[0]);HP p;HPInit(&p);for (int i = 0; i < n; i++){HPPush(&p, arr[i]);}int i = 0;while (!HPEmpty(&p)){arr[i++] = HPTop(&p);HPPop(&p);}for (int i = 0; i < n; i++){printf("%d ", arr[i]);}HPDesTroy(&p);
}

但是真正的堆排序不是我们上面这种写法,堆排序是借助堆的算法思想,而不能够直接使用堆的数据结构来辅助实现,这个时候我们来看一看怎么来实现堆的排序。

首先先将这三个我之前写的算法放到我们头文件里,可以用来直接使用。

void Swap(int* x, int* y);
void AdjustUp(HPDataType* arr, int child);
void AdjustDown(HPDataType* arr, int parent, int n);

(1)向下调整算法建堆的堆排序

我们建的是小堆

void HeapSort(int* arr, int n)
{//向下调整算法建堆for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(arr, i, n);}int end = n - 1;while (end){Swap(&arr[0], &arr[end]);AdjustDown(arr, 0, end);end--;}
}

测试

在这里插入图片描述

建的是小堆,排的是降序的数组。所以排升序建大堆,排降序建小堆。

向下调整算法的最差的时间复杂度为O(logn)。
所以向下调整算法建堆的时间复杂度为:O(n×log n)。
总的来说,向下调整堆排序的时间复杂度就为:O(nlogn)。

(2)向上调整算法建堆的堆排序

我们这次来建一个大堆

	//向上调整算法建堆for (int i = 0; i < n; i++){AdjustUp(arr, i);}int end = n - 1;while (end){Swap(&arr[0], &arr[end]);AdjustDown(arr, 0, end);end--;}

测试

在这里插入图片描述

向上调整算法最差的时间复杂度为:O(log n)。
向上调整算法建堆的时间复杂度:O(nlogn)
向上调整堆排序的时间复杂度:O(nlogn)。

我们通过总结得:向下调整算法建堆的时间复杂度比较好,越向下,结点个数逐渐增多,向下调整次数逐渐减少。向上调整算法建堆刚好相反。


二.实现链式结构二叉树

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

1.二叉树结点结构的定义

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

代码实现

构造一棵二叉树,将数据类型转化成char。

2.获取一个新结点

BTNode* buyNode(BTDataType x)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));if (newnode == NULL){perror("molloc fail!");exit(1);}newnode->data = x;newnode->left = newnode->right = NULL;return newnode;
}

3.手动构造一棵二叉树


BTNode* CreateTree()
{BTNode* nodeA = buyNode('A');BTNode* nodeB = buyNode('B');BTNode* nodeC = buyNode('C');BTNode* nodeD = buyNode('D');BTNode* nodeE = buyNode('E');BTNode* nodeF = buyNode('F');nodeA->left = nodeB;nodeA->right = nodeC;nodeB->left = nodeD;nodeC->left = nodeE;nodeC->right = nodeF;return nodeA;}

4.前序遍历

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

测试

在这里插入图片描述

5.中序遍历

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

测试

在这里插入图片描述

6.后序遍历

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

测试

在这里插入图片描述

7.二叉树结点个数

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

8.二叉树叶子结点个数

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

9.二叉树第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);
}

10.二叉树的深度/高度

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

11.二叉树查找值为x的结点

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BTNode* leftFind = BinaryTreeFind(root->left,x);if (leftFind){return leftFind;}BTNode* rightFind = BinaryTreeFind(root->right,x);if (rightFind){return rightFind;}return NULL;
}

12.二叉树销毁

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

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

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

相关文章

C和指针——预处理

预处理是编译前的过程&#xff0c;主要对define&#xff0c;include以及一些编译器定义的内容进行替换 #define的本质就是替换 1、例子 #define FOREVER for(;;) 2、例子 #define TEMPD "1231231231\ 123123123" \\如果太长了&#xff0c;可以用\换行 3、例子——可…

C++ set和map

目录 一、关联式容器 1.1 键值对 1.1.1 概念 1.1.2 pair 1.2 树形结构的关联式容器 二、set 2.1 set 的介绍 2.2 set 的使用 2.2.1 set 的构造 2.2.2 set 的迭代器 2.2.3 set 的容量操作 2.2.4 set 的修改操作 2.2.5 set 的查找操作 三、multiset 3.1 multiset …

「Mac畅玩AIGC与多模态07」开发篇03 - 开发第一个 Agent 插件调用应用

一、概述 本篇介绍如何在 macOS 环境下,基于 Dify 平台自带的网页爬虫插件工具,开发一个可以提取网页内容并作答的 Agent 应用。通过使用内置插件,无需自定义开发,即可实现基本的网页信息提取与智能体回答整合。 二、环境准备 1. 确认本地部署环境 确保以下环境已搭建并…

cline或业务系统集成n8n的工作流(MCP Server Trigger、Call n8n Workflow Tool node)

1.成果展示 1.1n8n的主工作流 1.2n8n的子工作流 1.3cline集成效果 2.实操过程 2.1Call n8n Workflow Tool node节点 Call n8n Workflow Tool节点是一个工具&#xff0c;它允许代理运行另一个n8n工作流并获取其输出数据。 在此页面上&#xff0c;您将找到“调用n8n工作流工具…

深入了解Linux系统—— 环境变量

命令行参数 我们知道&#xff0c;我们使用的指令它本质上也是一个程序&#xff0c;我们要执行这个指令&#xff0c;输入指令名然后回车即可执行&#xff1b;但是对于指令带选项&#xff0c;又是如何实现的呢&#xff1f; 问题&#xff1a;main函数有没有参数&#xff1f; 在我…

pip安装包时网络不畅,替换国内PyPI镜像源

1、PyPI 镜像源 1.1、定义 PyPI 镜像源是对 Python Package Index&#xff08;PyPI&#xff09;官方仓库的复制。 PyPI 是 Python 社区中最大的软件包仓库&#xff0c;存储着大量的 Python 包&#xff0c;供开发者们下载和使用。 然而&#xff0c;由于 PyPI 服务器位于国外&a…

贪心算法解决会议安排问题

文章目录 前言 一、什么是贪心算法&#xff1f; 贪心算法的基本概念&#xff1a;贪心算法并不从整体最优上加以考虑&#xff0c;所做的选择只是在某种意义上的局部最优选择。 二、会议安排题目 1.题目理解 2.思路剖析 总结 前言 本文将主要介绍贪心算法需要注意的地方以…

从入门到登峰-嵌入式Tracker定位算法全景之旅 Part 4 |IMU 死算与校正:惯性导航在资源受限环境的落地

Part 4 |IMU 死算与校正:惯性导航在资源受限环境的落地 本章聚焦 ESP32-S3 平台上如何利用 LSM6DS3 IMU 实现 死算(Dead Reckoning),并结合 零速更新(ZUPT) 或 磁力计辅助 进行 漂移校正,最终通过 EKF/UKF 融合提升定位精度。 一、传感器简介与校准 LSM6DS3 主要参数 加速…

力扣1128题解

记录 2525.5.4 题目&#xff1a; 思路&#xff1a; 先将dominoes[i]的二元全部变为前大后小的形式&#xff0c;再遍历该数组&#xff0c;用数组来记录。 代码&#xff1a; class Solution {public int numEquivDominoPairs(int[][] dominoes) {int [] [] cnt new int [10…

with的用法

Python SQLite 操作详解 本文档详细解释了使用 Python 操作 SQLite 数据库时涉及的关键概念和代码实践&#xff0c;包括 with 语句、事务处理、批量插入以及相关的优化建议。 一、with 语句的作用&#xff08;自动关门的保险库&#xff09; with sqlite3.connect(city_1301.d…

力扣解题汇总(困难)

文章目录 技巧42_接雨水 技巧 42_接雨水 class Solution {public int trap(int[] height) {int LMax 0, RMax 0;int len height.length;int[] L2R new int[len];int[] R2L new int[len];//计数每一个格的左右边最高柱for (int i 0; i < len; i) {LMax Math.max(LMa…

【Redis】Redis常用命令

4.Redis常见命令 4.1 Redis数据结构介绍 Redis是一个key-value的数据库&#xff0c;key一般是String类型&#xff0c;不过value的类型多种多样&#xff1a; 命令太多&#xff0c;不需要死记&#xff0c;学会查询就好了~ Redis为了方便我们学习&#xff0c;将操作不同数据类型…

Ubuntu 系统上广受好评的浏览器推荐

日常使用与开发者首选 Firefox 特点&#xff1a;开源、隐私保护强大&#xff0c;支持丰富扩展&#xff08;如开发者工具、广告拦截&#xff09;&#xff0c;默认预装且跨平台兼容368。 适用场景&#xff1a;日常浏览、开发者调试&#xff08;支持实时 CSS/JS 编辑&#xff09;、…

Rust Trait 学习

概述 特征&#xff08;trait&#xff09;是rust中的概念&#xff0c;类似于其他语言中的接口&#xff08;interface&#xff09;。特征定义了一个可以被共享的行为&#xff0c;只要实现了特征&#xff0c;你就能使用该行为。 如果不同的类型具有相同的行为&#xff0c;那么我们…

JavaScript性能优化实战(9):图像与媒体资源优化

引言 在当今视觉驱动的网络环境中,图像和媒体资源往往占据了网页总下载量的60%-80%,因此对图像和媒体资源进行有效优化已成为前端性能提升的关键领域。尽管网络带宽持续提升,但用户对加载速度的期望也在不断提高,特别是在移动设备和网络条件不稳定的场景下。 本文作为Jav…

NHANES指标推荐:LC9

文章题目&#xff1a;Association between lifes crucial 9 and kidney stones: a population-based study DOI&#xff1a;10.3389/fmed.2025.1558628 中文标题&#xff1a;生命的关键 9 与肾结石之间的关联&#xff1a;一项基于人群的研究 发表杂志&#xff1a;Front Med 影响…

谷歌 NotebookLM 支持生成中文播客

谷歌 NotebookLM 支持生成中文播客。 2025 年 4 月 29 日&#xff0c;NotebookLM 宣布其 “音频概览”&#xff08;Audio Overviews&#xff09;功能新增 76 种语言支持&#xff0c;其中包括中文。用户只需将文档、笔记、研究材料等上传至 NotebookLM&#xff0c;然后在设置中选…

ElasticSearch深入解析(十):字段膨胀(Mapping 爆炸)问题的解决思路

文章目录 一、核心原理&#xff1a;动态映射的双刃剑1. 动态映射的工作机制2. 映射爆炸的触发条件3. 底层性能损耗 二、典型场景与案例分析1. 日志系统&#xff1a;动态标签引发的灾难2. 物联网数据&#xff1a;设备属性的无序扩展 三、系统性解决方案1. 架构层优化2. 配置层控…

交互式智能体面临长周期决策和随机环境反馈交互等挑战 以及解决办法

交互式智能体面临长周期决策和随机环境反馈交互等挑战 以及解决办法 目录 交互式智能体面临长周期决策和随机环境反馈交互等挑战 以及解决办法随机初始化参数,lora但是训练需要更加细粒度的评价指数(对思考过程评价,对得出结果的证明评价,对结果评价)用户进看到结果《RAGE…

4:机器人目标识别无序抓取程序二次开发

判断文件是否存在 //判断文件在不在 int HandEyeCalib::AnsysFileExists(QString FileAddr) {QFile File1(FileAddr);if(!File1.exists()){QMessageBox::warning(this,QString::fromLocal8Bit("提示"),FileAddrQString::fromLocal8Bit("文件不存在"));retu…