数据结构—链式二叉树-C语言

        代码位置:test-c-2024: 对C语言习题代码的练习 (gitee.com)

一、前言:

        在现实中搜索二叉树为常用的二叉树之一,今天我们就要通过链表来实现搜索二叉树。实现的操作有:建二叉树、前序遍历、中序遍历、后序遍历、求树的节点个数、求树的高度、求k层节点个数、查找节点、层序遍历,判断是否是完全二叉树,二叉树的销毁。

二、代码实现:

2.0-开辟空间函数及结构体:

        对于链表我们可以定义一个开辟空间的函数以便于后继的操作。对于结构体成员中我们需要包含节点值data和左右子树节点。

代码如下:

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include "Queue.h"typedef int BTDataType;
typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;BTNode* BuyNode(BTDataType x)		//开辟空间
{BTNode* node = (BTNode*)malloc(sizeof(BTNode));if (node == NULL){perror("malloc node");return NULL;}node->data = x;node->left = NULL;node->right = NULL;return node;
}

2.1-建二叉树:

        对于建二叉树我们需要手动搓一个二叉树。

建的树如图所示:

代码如下:

BTNode* CreatTree()			//建二叉树
{BTNode* node1 = BuyNode(1);BTNode* node2 = BuyNode(2);BTNode* node3 = BuyNode(3);BTNode* node4 = BuyNode(4);BTNode* node5 = BuyNode(5);BTNode* node6 = BuyNode(6);node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;return node1;
}

2.2-前序遍历:

        二叉树前序遍历规则为:先访问根节点在访问左子树最后访问右子树。我这里是通过函数递归实现的访问。

代码如下:

void PreOrder(BTNode* root)			//前序遍历
{if (root == NULL){printf("NULL ");return;}printf("%d ", root->data);PreOrder(root->left);PreOrder(root->right);
}

2.3-中序遍历:

        二叉树中序遍历规则为:先访问左子树在访问根节点最后访问右子树。我这里是通过函数递归实现的访问。

代码如下:

void InOrder(BTNode* root)			//中序遍历
{if (root == NULL){printf("NULL ");return;}InOrder(root->left);printf("%d ", root->data);InOrder(root->right);
}

2.4-后序遍历:

        二叉树后序遍历规则为:先访问左子树在访问右子树最后访问根节点。我这里是通过函数递归实现的访问。

代码如下:

void PostOrder(BTNode* root)			//后序遍历
{if (root == NULL){printf("NULL ");return;}PostOrder(root->left);PostOrder(root->right);printf("%d ", root->data);
}

2.5-求树的节点个数:

        这里是通过三目操作符以及递归来实现的统计节点个数。原理是如果该节点不是空节点则整体个数加1,然后继续访问下一子树,直到遍历完为止。

代码如下:

int TreeSize(BTNode* root)         //求节点个数
{return root == NULL ? 0: TreeSize(root->left)+ TreeSize(root->right)+ 1;
}

2.6-求树的高度:

        这里是通过leftHeight和rightHeight来存储左右子树高度值,然后在return中通过三目运算符来返回高的那一子树在加1(这里加1是节点本身占一个高度)

代码如下:

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

2.7-求k层节点个数:

        这里是通过递归传k-1是为了找到k层的所有节点若存在则返回1,不存在返回0然后将所有返回值相加返回即是第k层的节点个数。

代码如下:


int TreeLeave(BTNode* root,int k)		//求k层节点个数
{assert(k > 0);if (root == NULL){return 0;}if(k==1){return 1;}return TreeLeave(root->left, k - 1) +TreeLeave(root->right, k - 1);
}

2.8-查找节点:

        这里是通过递归遍历一遍树查找是否存在查找值若存在则返回该节点,若不存在则返回NULL。(注:这个函数只能查找出该值前序遍历第一次出现的位置)

代码如下:


BTNode* BinaryTreeFind(BTNode* root, BTDataType x)		//查找
{if (root == NULL){return 0;}if (root->data == x){return root;}BTNode* p = BinaryTreeFind(root->left, x);if(p)return p;BTNode * q=BinaryTreeFind(root->right, x);if (q )return q;return NULL;
}

2.9-层序遍历:

        这里需要用到队列以前的博客里我们实现过队列,所以这里我们可以当个CV工程师将以前的代码复制过来即可。

队列代码:

#pragma once#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>typedef struct BinaryTreeNode* QDataType;
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QNode;typedef struct Queue
{QNode* head;QNode* tail;int size;
}Queue;void QueueInit(Queue* pq);								//初始化
void QueueDestory(Queue* pq);							//释放销毁
void QueuePush(Queue* pq,QDataType x);		//入队	
void QueuePop(Queue* pq);								//出队
int QueueSize(Queue* pq);								//元素个数
bool QueueEmpty(Queue* pq);							//判断队空
QDataType QueueFront(Queue* pq);					//队头数据
QDataType QueueBack(Queue* pq);					//队尾数据
#define _CRT_SECURE_NO_WARNINGS 1#include "Queue.h"void QueueInit(Queue* pq)			    					//初始化
{assert(pq);pq->head = pq->tail = NULL;pq->size = 0;
}void QueueDestory(Queue* pq)     					//释放销毁
{assert(pq);QNode* cur =pq->head;while (cur){pq->head = cur->next;free(cur);cur = NULL;cur = pq->head;}pq->head = pq->tail = NULL;pq->size = 0;
}void QueuePush(Queue* pq, QDataType x)		//入队	
{QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc");return;}newnode->data = x;newnode->next = NULL;if (pq->head == NULL){assert(pq->tail==NULL);pq->head = pq->tail=newnode;}else{pq->tail->next = newnode;pq->tail = newnode;}pq->size++;
}void QueuePop(Queue* pq)								//出队
{assert(pq);assert(!QueueEmpty(pq));QNode* del = pq->head;pq->head = pq->head->next;free(del);del = NULL;if (pq->head == NULL){pq->tail = NULL;}pq->size--;
}int QueueSize(Queue* pq)								//元素个数
{assert(pq);return pq->size;
}bool QueueEmpty(Queue* pq)							//判断队空
{assert(pq);return pq->size == 0;
}QDataType QueueFront(Queue* pq)					//队头数据
{assert(pq);assert(!QueueEmpty(pq));return pq->head->data;
}QDataType QueueBack(Queue* pq)					//队尾数据
{assert(pq);assert(!QueueEmpty(pq));return pq->tail->data;
}

遍历代码如下:

void LevelOrder(BTNode* root)				//层序遍历
{Queue p;QueueInit(&p);if(root)QueuePush(&p, root);while (!QueueEmpty(&p)){BTNode* front = QueueFront(&p);		//取队列首元素的值QueuePop(&p);printf("%d ", front->data);if (front->left)			//入下一层元素{QueuePush(&p, front->left);}if (front->right){QueuePush(&p, front->right);}}QueueDestory(&p);
}

        层序遍历代码执行的过程如图所示:

2.10-判断是否是完全二叉树:

        判断完全二叉树是通过层序遍历和队列来实现。注意这里的层序遍历遇到空树也需要入队,为了判断二叉树是否为完全二叉树。原理://层序遍历第一次遇到NULL时若后面没有数据节点则是完全二叉树,反之则不是

代码如下:

bool TreeComplete(BTNode* root)		//判断是否是完全二叉树
{Queue pq;QueueInit(&pq);QueuePush(&pq, root);while (!QueueEmpty(&pq)){BTNode* front = QueueFront(&pq);if (QueueFront(&pq) == NULL){break;}QueuePop(&pq);QueuePush(&pq, front->left);QueuePush(&pq, front->right);}//层序遍历第一次遇到NULL时若后面没有数据节点则是完全二叉树,反之则不是while (!QueueEmpty(&pq))				{if (QueueFront(&pq) != NULL){QueueDestory(&pq);return false;}QueuePop(&pq);}QueueDestory(&pq);return true;
}

2.11-二叉树的销毁:

        二叉树销毁需遍历一遍链表,这里采用后序遍历比较方便,因为另外两个遍历都会因为释放根节点后左右子节点不好释放而产生不必要的麻烦,所以这里最好是使用后序遍历。注意这里只是释放掉了空间,因为这里是一级指针所以这里置空属于局部变量不会影响外部,所以在主函数调用时我们需手动置空。

如图所示:

代码如下:

void TreeDestory(BTNode* root)		//销毁二叉树
{if (root == NULL)return;TreeDestory(root->left);TreeDestory(root->right);free(root);
}

三、结语:

递归效果图展示:

最终效果图为:

        上述内容,即是我个人对数据结构-链式二叉树-搜索二叉树-C语言的个人见解以及自我实现。若有大佬发现哪里有问题可以私信或评论指教一下我这个小萌新。非常感谢各位友友们的点赞,关注,收藏与支持,我会更加努力的学习编程语言,还望各位多多关照,让我们一起进步吧!

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

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

相关文章

SMU Summer 2024 Contest Round 4

SMU Summer 2024 Contest Round 4 2024.7.16 9:00————11:00 过题数3/7 补题数6/7 Made Up H and V Moving Piece Sum of Divisors Red and Green Apples Rem of Sum is Num Keep Connect A - Made Up 题解&#xff1a; 给定三个数组a&#xff0c;b&#xff0c;c&#xf…

MySQL日期和时间相关函数

目录 1. 获取当前时间和日期 2. 获取当前日期 3. 获取当前时间 4. 获取单独的年/月/日/时/分/秒 5. 添加时间间隔 date_add ( ) 6. 格式化日期 date_format ( ) 7. 字符串转日期 str_to_date () 8. 第几天 dayofxx 9. 当月最后一天 last_day ( ) 10. 日期差 datedif…

H. Beppa and SwerChat【双指针】

思路分析&#xff1a;运用双指针从后往前扫一遍&#xff0c;两次分别记作数组a&#xff0c;b&#xff0c;分别使用双指针i和j来扫&#xff0c;如果一样就往前&#xff0c;如果不一样&#xff0c;i–,ans #include<iostream> #include<cstring> #include<string…

SQL server 练习题2

课后作业 作业 1&#xff1a;自己查找方法&#xff0c;将 homework_1.xls 文件数据导入到 SQLServer 的 homework 数据库中。数据导入完成后&#xff0c;把表名统一改为&#xff1a;外卖表 如下所示&#xff1a; 作业 2&#xff1a;找出所有在 2020 年 5 月 1 日至 5 月 31 …

Zookeeper之CAP理论及分布式一致性算法

CAP理论 CAP理论告诉我们&#xff0c;一个分布式系统不可能同时满足以下三种 一致性&#xff08;C:consistency&#xff09;可用性&#xff08;A:Available&#xff09;分区容错性&#xff08;P:Partition Tolerance&#xff09; 这三个基本要求&#xff0c;最多只能同时满足…

python 语法学习 day2

python有七大数据类型, 数据类型转换, 多变量赋值与print间隔, split函数, int用法总结python有七大数据类型&#xff1a; &#xff08;1&#xff09;数字&#xff08;Number&#xff09;&#xff1a;int(整型&#xff0c;长整型)&#xff0c;float(浮点型)&#xff0c;com…

部署k8s 1.28.9版本

继上篇通过vagrant与virtualBox实现虚拟机的安装。笔者已经将原有的vmware版本的虚拟机卸载掉了。这个场景下&#xff0c;需要重新安装k8s 相关组件。由于之前写的一篇文章本身也没有截图。只有命令。所以趁着现在。写一篇&#xff0c;完整版带截图的步骤。现在行业这么卷。离…

SpringBoot中常用的注解及其用法

1. 常用类注解 RestController和Controller是Spring中用于定义控制器的两个类注解. 1.1 RestController RestController是一个组合类注解,是Controller和ResponseBody两个注解的组合,在使 用 RestController 注解标记的类中&#xff0c;每个方法的返回值都会以 JSON 或 XML…

【Android安全】Ubuntu 下载、编译 、刷入Android-8.1.0_r1

0. 环境准备 Ubuntu 16.04 LTS&#xff08;预留至少95GB磁盘空间&#xff0c;实测占94.2GB&#xff09; Pixel 2 XL 要买欧版的&#xff0c;不要美版的。 欧版能解锁BootLoader、能刷机。 美版IMEI里一般带“v”或者"version"&#xff0c;这样不能解锁BootLoader、…

网络安全-网络安全及其防护措施2

6.安全设计和日志 安全审计 安全审计是对系统和网络活动进行检查和记录的过程&#xff0c;确保合规性和安全性。审计过程可以帮助发现潜在的安全漏洞和违规行为&#xff0c;并验证系统配置和操作的正确性。 定期审计 定义&#xff1a;定期检查系统和网络的安全配置和活动记录…

394. 字符串解码 739. 每日温度(LeetCode热题100)

394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; curr_str&#xff1a;遍历整个字符串时 如果左边有[&#xff0c;且无相应右括号和其匹配&#xff0c;那么curr_str就表示该[到当前位置的解码字符串如果左边的[]已经匹配&#xff0c;或者没有[]&#xff0c;curr_siz…

找不到vcruntime140_1.dll 无法执行的相关解决方法,如何高效率修复vcruntime140_1.dll

当出现“找不到 vcruntime140_1.dll 无法执行”这类提示时&#xff0c;意味着你的系统中的 vcruntime140_1.dll 文件已经缺失或者损坏。为了恢复并正常启动你的程序&#xff0c;你需要对这个 DLL 文件进行修复。接下来&#xff0c;我们将详细介绍如何进行这一操作。 一.找不到v…

数学建模·层次分析法

层次分析法 LAF 定义 评价体系的优劣影响&#xff0c;计算评价指标的权重的一种方法 主观性较强&#xff0c;现在一般不用 主要步骤 关键在于一致性检验和求权值 权重的计算 注意权重之和为1&#xff0c;需要归一化 算数平均法 特征值法 矩阵的一致性检验 为什么要检验…

【C语言】原码、反码、补码详解 -《码上有道 ! 》

目录 原码、反码、补码详解及其在C语言中的应用一、原码&#xff08;Sign-Magnitude&#xff09;1.1 定义与表示1.2 历史来源与作用1.3 示例1.4 C语言示例1.5 代码运行结果 二、反码&#xff08;Ones Complement&#xff09;2.1 定义与表示2.2 历史来源与作用2.3 示例2.4 C语言…

sentinel网关限流配置及使用

sentinel控制台源码&#xff1a;https://download.csdn.net/download/yixin605691235/89543923 sentinel控制台jar包&#xff1a;https://download.csdn.net/download/yixin605691235/89543931 不同环境直接修改jar包中的application.yml文件中的nacos地址就可以了。 一、网关限…

【LeetCode 0169】【摩尔投票算法】主元素

Majority Element Given an array nums of size n, return the majority element. The majority element is the element that appears more than ⌊n / 2⌋ times. You may assume that the majority element always exists in the array. Example 1: **Input:** nums [3…

大数据信用查询有哪些问题值得注意呢?

随着大数据技术的不断发展&#xff0c;大数据信用报告成为一种新型的信用风险检测工具&#xff0c;被很多的银行和机构广泛用于信用风险评估&#xff0c;那大数据信用查询有哪些问题值得注意呢?本文就带大家一起去了解一下&#xff0c;希望对你有一定的帮助。 大数据信用查询这…

JsonCPP源码分析——分配器和配置器

1、allocator.h文件 该文件定义了一个分配器模版&#xff0c;该文件主要使用了内存对齐控制、rebind机制(C 标准库的分配器接口要求提供 rebind 机制&#xff0c;以支持不同类型的分配)、::operator new、std::addressof等技术。 内存对齐控制&#xff1a;之所以先保存当前内存…

《C++ 入门:第一个小程序》

《C 入门&#xff1a;第一个小程序》 在学习 C 的旅程中&#xff0c;编写第一个小程序是一个令人兴奋的时刻。它就像打开一扇通往新编程世界的大门&#xff0c;让我们初步领略 C 的魅力。 C 是一种强大而灵活的编程语言&#xff0c;广泛应用于各种领域&#xff0c;从系统编程…

python 方向梯度直方图(HOG)算法 【附两种实现方法并可视化】

目录 一、概述1.1 算法定义1.2 实现过程二、方法1(skimage库)2.1 代码实现2.2 结果示例三、方法2(cv2库)3.1 代码实现3.2 结果示例四、结果对比🙋 结果预览 一、概述 1.1 算法定义 方向梯度直方图(Histogram of Oriented Gradient,HOG):是应用在计算机视觉和图像处…