二叉树链式结构

1.前置说明

 我们手动构建一棵二叉树:

注意:上述代码并不是创建二叉树的方式

从概念中可以看出,二叉树定义是递归式的,因此后序基本操作中基本都是按照该概念实现的

2.二叉树的遍历

2.1前序、中序以及后序遍历

学习二叉树结构,最简单的方式就是遍历

所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题

遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础

其实可以这样理解:

  • 前序遍历:根->左子树->右子树
  • 中序遍历:左子树->根->右子树
  • 后序遍历:左子树->右子树->根

以下面这个二叉树为例:

  • 前序遍历:1->2->3->4->5->6
  • 中序遍历:3->2->1->5->4->6
  • 后序遍历:3->2->5->6->4->1

由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根的左子树和根的右子树

NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历

遍历的实现需要用到递归

2.2前序遍历

代码实现是这样的:

2.3中序遍历

2.4后序遍历

2.5层序遍历

层序遍历:除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。

设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历

我们可以利用队列先进先出的特点来实现:

  • 定义一个q队列
  • 如果root不为空,则将root入队列
  • 用front来保存队头数据,将队头数据pop,打印队头数据;然后遍历下一层:如果左孩子不为空,左孩子入队列;右孩子不为空,右孩子入队列;当队列不为空则继续遍历下一层,直到队列为空退出循环

关于这块的指针问题,我们画图解释一下

我们修改val也为BTNode*类型

分层打印

我们可以定义一个levelsize保存每一层的数据个数,控制一层一层打印

队列的size就是下一层的数据个数

效果是这样的

3.节点个数

3.1二叉树的节点个数

3.1叶子节点个数

4.求树的高度

  1. 如果为空 返回0
  2. 不为空 左子树和右子树高度更高的那个+1

5.求第k层的节点个数

  1. 如果为空 返回0
  2. 如果不为空 且k=1 返回1
  3. 如果不为空 且k>1 返回左子树的k-1层+右子树的k-1层

5.查找值为x的节点 

6.构建一棵链式二叉树

假设给一个前序遍历的数组,将其构建成一棵二叉树

7.判断完全二叉树

完全二叉树的节点都是连续的,所以不可能出现一个NULL节点的后面存在非空节点的情况,我们用层序遍历的思路,入队列的时候不管是不是NULL节点都入队列,出队列的时候如果遇到NULL节点,则停止出队列,判断后面是否还有非空节点,我们用while循环来控制,如果队列不为空则出队列,如果队头数据有不为空的情况,则返回false

8.销毁二叉树

销毁我们为了防止形成野指针,从下往上,从左往右,即后序遍历依次销毁

代码示例 

Queue

Queue.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
//创建
typedef struct BTNode* QDataType;
typedef struct QueueNode
{QDataType val;struct QueueNode* next;
}QNode;typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;
//把队列的头尾封装在一个结构体中//初始化
void QInit(Queue* pq);
//销毁
void QDestroy(Queue* pq);//入队列
void QPush(Queue* pq, QDataType x);
//出队列
void QPop(Queue* pq);
//取队头数据
QDataType QFront(Queue* pq);
//取队尾数据
QDataType QBack(Queue* pq);
//判空
bool QEmpty(Queue* pq);
//返回队列有效元素个数
int QSize(Queue* pq);

Queue.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"
//初始化
void QInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;pq->size = 0;
}
//销毁
void QDestroy(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur){QNode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}
//入队列
void QPush(Queue* pq, QDataType x)
{assert(pq);//创建newnodeQNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");return;}newnode->val = x;newnode->next = NULL;if (pq->ptail == NULL){pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}
//出队列
void QPop(Queue* pq)
{assert(pq);assert(pq->phead);QNode* del = pq->phead;pq->phead = pq->phead->next;free(del);del = NULL;if (pq->phead == NULL){pq->ptail = NULL;//防止ptail成为野指针}pq->size--;
}
//取队头数据
QDataType QFront(Queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->val;
}
//取队尾数据
QDataType QBack(Queue* pq)
{assert(pq);assert(pq->ptail);return pq->ptail->val;
}
//判空
bool QEmpty(Queue* pq)
{assert(pq);return pq->phead == NULL;
}
//返回队列有效元素个数
int QSize(Queue* pq)
{assert(pq);return pq->size;
}

TreeNode

TreeNode.c

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include "Queue.h"
//创建
typedef char BTDataType;
typedef struct BTNode
{BTDataType data;struct BTNode* left;struct BTNode* right;
}BTNode;//BTNode* BuyNode(BTDataType x)
//{
//	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
//	node->data = x;
//	node->left = NULL;
//	node->right = NULL;
//	return node;
//}
//构建二叉树
BTNode* BTCreate(BTDataType*a,int*pi)
{if (a[*pi] == '#'){(*pi)++;return NULL;}BTNode* root = (BTNode*)malloc(sizeof(BTNode));if (root == NULL){perror("malloc fail");exit(-1);}root->data = a[(*pi)++];root->left = BTCreate(a,pi);root->right = BTCreate(a,pi);return root;
}
//先序遍历
void BTPrevOrder(BTNode* root)
{if (root == NULL){printf("# ");return;}printf("%c ", root->data);BTPrevOrder(root->left);BTPrevOrder(root->right);
}
//中序遍历
void BTInOrder(BTNode* root)
{if (root == NULL){printf("# ");return;}BTInOrder(root->left);printf("%c ", root->data);BTInOrder(root->right);
}
//后序遍历
void BTPostOrder(BTNode* root)
{if (root == NULL){printf("# ");return;}BTPostOrder(root->left);BTPostOrder(root->right);printf("%c ", root->data);
}
// 层序遍历
void BTLevelOrder(BTNode* root)
{Queue q;QInit(&q);if (root)QPush(&q, root);int levelsize = 1;while (!QEmpty(&q)){while (levelsize--){BTNode* front = QFront(&q);QPop(&q);printf("%c ", front->data);if (front->left)QPush(&q, front->left);if (front->right)QPush(&q, front->right);}printf("\n");levelsize = QSize(&q);}printf("\n");QDestroy(&q);
}
//判断完全二叉树
bool BTComplete(BTNode* root)
{Queue q;QInit(&q);if (root)QPush(&q, root);int levelsize = 1;while (!QEmpty(&q)){BTNode* front = QFront(&q);QPop(&q);if (front == NULL)break;QPush(&q, front->left);QPush(&q, front->right);}while (!QEmpty(&q)){BTNode* front = QFront(&q);QPop(&q);if (front){QDestroy(&q);return false;}}QDestroy(&q);return true;
}
//销毁
void BTDestroy(BTNode* root)
{if (root == NULL)return;BTDestroy(root->left);BTDestroy(root->right);free(root);
}
//二叉树结点个数
//static int size = 0;
int BTSize(BTNode* root)
{/*if (root == NULL){return;}++size;BTSize(root->left);BTSize(root->right);return size;*/return root == NULL ? 0 : BTSize(root->left) + BTSize(root->right)+1;
}
//叶子节点个数
int BTLSize(BTNode* root)
{/*if (root == NULL){return 0;}return root->left == NULL && root->right == NULL ? 1:BTLSize(root->left) + BTLSize(root->right);*/return (root == NULL ? 0 : (root->left == NULL && root->right == NULL ? 1 :BTLSize(root->left) + BTLSize(root->right)));
}
//求树的高度
int BTHeight(BTNode* root)
{if (root == NULL)return 0;int leftHeight = BTHeight(root->left);int rightHeight = BTHeight(root->right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
//求第k层的节点个数
int BTLKSize(BTNode* root, int k)
{assert(k > 0);if (root == NULL)return 0;if (k == 1)return 1;return BTLKSize(root->left, k - 1) + BTLKSize(root->right, k - 1);
}
//查找值为x的节点
BTNode* BTFind(BTNode* root, BTDataType x)
{if (root == NULL)return NULL;if (root->data == x)return root;BTNode* leftnode = BTFind(root->left, x);if (leftnode)return leftnode;BTNode* rightnode = BTFind(root->right, x);if (rightnode)return rightnode;return NULL;
}
int main()
{//char a[] = "ABD##E#H##CF##G##";char a[] = "ABC##D##EF##G##";int i = 0;BTNode* root = BTCreate(a,&i);BTPrevOrder(root);printf("\n");BTInOrder(root);printf("\n");BTPostOrder(root);printf("\n");int size1 = BTSize(root);printf("%d\n", size1);int size2 = BTSize(root);printf("%d\n", size2);int size3 = BTLSize(root);printf("%d\n", size3);int h = BTHeight(root);printf("%d\n", h);int s = BTLKSize(root, 3);printf("%d\n", s);BTLevelOrder(root);printf("%d\n", BTComplete(root));BTDestroy(root);root = NULL;return 0;
}

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

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

相关文章

库函数qsort的使用及利用冒泡排序模拟实现qsort

文章目录 &#x1f680;前言&#x1f680;void*类型指针&#x1f680;库函数qsort的使用&#x1f680;利用冒泡排序实现库函数qsort() &#x1f680;前言 今天阿辉将为大家介绍库函数qsort的使用&#xff0c;还包括利用冒泡排序模拟实现qsort以及void*类型的指针&#xff0c;关…

数据结构与算法之美学习笔记:31 | 深度和广度优先搜索:如何找出社交网络中的三度好友关系?

目录 前言什么是“搜索”算法&#xff1f;广度优先搜索&#xff08;BFS&#xff09;深度优先搜索&#xff08;DFS&#xff09;解答开篇内容小结 前言 本节课程思维导图&#xff1a; 社交网络中&#xff0c;有一个六度分割理论&#xff0c;具体是说&#xff0c;你与世界上的另一…

Web安全-初识SQL注入(一)

1、初识SQL注入 1.1、什么是注入&#xff1f; 将不受信任的数据作为命令或查询的一部分发送到解析器时&#xff0c;会产生诸如SQL注入、NoSQL注入、OS 注入和LDAP注入的注入缺陷。攻击者的恶意数据可以诱使解析器在没有适当授权的情况下执行非预期命令或访问数据。 注入能导…

mysql有哪些锁,理解各种表锁和行锁

全局锁 主要用于数据库的备份&#xff0c;但会使得备份期间不能有任何事务插入删除更新数据&#xff0c;这很影响实际业务。所以通常不用这个全局锁来完成数据库的备份。假设数据库的存储引擎支持可重复读&#xff0c;那么常见的方法是通过MVCC来实现的&#xff0c;也就是备份…

解决ant-design-vue中Select组件v-model值为空字符串不显示placeholder的bug

方法一&#xff1a; 1.找到node_modules/ant-design-vue/es/vc-select/SingleSelector.js文件 搜索renderPlacehoder方法 将其修改为 const renderPlacehoder () > {const list props.values.filter(val > val.value ! );if (list[0]) {return null}... }2.在此文件中…

ROS2教程05 ROS2服务

ROS2服务 版权信息 Copyright 2023 Herman YeAuromix. All rights reserved.This course and all of its associated content, including but not limited to text, images, videos, and any other materials, are protected by copyright law. The author holds all right…

Dockerfile脚本编写流程及示例

学习dockerfile指令 Dockerfile 指令 说明 FROM 指定基础镜像 MAINTAINER 声明镜像的维护者 LABEL 添加元数据标签 RUN 在容器中执行命令 CMD 容器启动后默认执行的命令 EXPOSE 暴露容器的端口 ENV 设置环境变量 ADD 将文件、目录或远程文件添加到容器中 COP…

Maxwell学习笔记

1 概述 Maxwell 是由美国 Zendesk 开源&#xff0c;用 Java 编写的 MySQL 实时抓取软件。 实时读取MySQL 二进制日志 Binlog&#xff0c;并生成 JSON 格式的消息&#xff0c;作为生产者发送给 Kafka&#xff0c;Kinesis、RabbitMQ、Redis、Google Cloud Pub/Sub、文件或其它平台…

InnoDB的锁

自增锁 自增锁是一种特殊的表级别锁&#xff08;table-level lock&#xff09;&#xff0c;专门针对事务插入 AUTO_INCREMENT 类型的列。最简单的情况&#xff0c;如果一个事务正在往表中插入记录&#xff0c;所有其他事务的插入必须等待&#xff0c;以便第一个事务插入的行&a…

arcgis投影栅格不可用

1、使用【投影栅格】工具进行栅格数据投影转换时报错。 解决方法&#xff1a;如果使用的是arcgis10.5及以下的版本&#xff0c;则需要更换更高的版本&#xff0c;因为这个是软件问题&#xff0c;需要更换到arcgis10.6及以上版本&#xff0c;更高级别的版本已经修复了这个问题。…

优酷新国风动漫《师兄啊师兄 第二季》强势定档 看李长寿稳健归来!

看新国风&#xff0c;上优酷动漫&#xff01;由优酷出品&#xff0c;玄机科技制作&#xff0c;改编自阅文集团旗下起点读书小说《我师兄实在太稳健了》&#xff08;作者&#xff1a;言归正传&#xff09;的修仙喜剧动画《师兄啊师兄》第二季《海神扬名篇》今日正式官宣定档&…

HCIP —— 重发布

目录 路由重发布背景&#xff1a; 路由重发布的作用&#xff1a; ​编辑 部署条件&#xff1a; 1.必须存在ASBR设备 2.需要关注种子度量值 重发布的规则 重发布的名词 重发布的方向性问题&#xff08;单向/双向&#xff09; 重发布的ASBR数量问题 单点---只存在一个AS…

陀螺仪防抖术语

陀螺仪防抖术语 fov 视场角 drift 零偏   MotionFusion即运动传感器的融合补偿&#xff0c;对陀螺仪、加速度计等运动测量器件的数据 进行预处理&#xff0c;通过标定和补偿&#xff0c;为防抖提供校准后的陀螺仪数据 ratio 系数 gyro 陀螺仪 calibration 校准 标定 DIS&…

实力出圈,开源网安连续4年入选中国网络安全企业100强

近日&#xff0c;安全牛第十一版《中国网络安全企业100强》正式发布。开源网安突出的综合实力、技术创新能力&#xff0c;以及前沿技术的落地应用成果&#xff0c;再次受到权威认可&#xff0c;从数百家安全厂商中脱颖而出&#xff0c;连续多年上榜百强榜单。 《中国网络安全企…

2023年个人工作总结怎么写?工作任务完成自动记录的待办软件

2023年已经接近尾声&#xff0c;不少人已经开始期待新的一年到来了。不过对于大多数职场人士来说&#xff0c;最近还有一项让人头疼的任务需要完成&#xff0c;这就是撰写2023年个人工作总结。 那么年度个人工作总结怎么写呢&#xff1f;其实很简单&#xff0c;年度工作总结一…

【软件安装】在vm上安装Centos操作系统

文章目录 下载iso镜像安装 下载iso镜像 centos下载地址&#xff1a;阿里巴巴centos下载地址 安装 基本按照下面的步骤走就可以了 新手一般建议典型就可以了&#xff0c;而且自定义也改不了什么东西&#xff0c;没太大必要 选择自己下载的iso镜像文件 用户名和密码 安装位置 指…

webGL开发虚拟实验室技术方案

开发虚拟实验室涉及到模拟实际实验环境和过程&#xff0c;同时提供用户互动性和学习体验。以下是一个可能的技术方案&#xff0c;用于实现这样的虚拟实验室&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合…

【EI会议征稿中】第五届人工智能与机电自动化国际学术会议(AIEA 2024)

第五届人工智能与机电自动化国际学术会议&#xff08;AIEA 2024&#xff09; 2024 5th International Conference on Artificial Intelligence and Electromechanical Automation 第五届人工智能与机电自动化国际学术会议&#xff08;AIEA 2024&#xff09;将于2024年3月8-10…

极致体验云上无缝协作

探索SOLIDWORKS云上之旅 谁适合应用3DEXPERIENCE云平台? 迈向云策略的数字化转型企业、加速新品上市的企业创新部门、资源有限的小微及初创企业 什么是3DEXPERIENCE云平台? 3DEXPERIENCE(3DX)是一种业务与创新平台,可让所有组织整体实时了解业务活动和生态系统&#xff0c…

SOLIDWORKS 2024新功能之Simulation篇

SOLIDWORKS 2024 新功能 Simulation篇目录概述 • 自动保存模型文件 • 壳体的接合交互 • 收敛检查图解 • 去耦合混合自由体模式 • Direct Sparse 解算器已停用 • 增强型轴承接头 • 复制算例时排除网格和结果 • 导出模型形状数据 • 网格性能 • 性能增强功能 …