【数据结构】二叉树的链式结构及实现

目录

1. 前置说明

2. 二叉树的遍历

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

2.2 层序遍历

3. 节点个数及高度等

4. 二叉树的创建和销毁


1. 前置说明

在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在大家对二叉树结构掌握还不够深入,为了降低大家学习成本,此处手动快速创建一棵简单的二叉树,快速进入二叉树操作学习,等二叉树结构了解的差不多时,我们反过头再来研究二叉树真正的创建方式。

typedef int BTDataType;
typedef struct BinaryTreeNode
{BTDataType _data;struct BinaryTreeNode* _left;struct BinaryTreeNode* _right;
}BTNode;BTNode* CreatBinaryTree()
{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;
}

注意:上述代码并不是创建二叉树的方式,真正创建二叉树方式后序详解重点讲解。

再看二叉树基本操作前,再回顾下二叉树的概念,二叉树是

  1. 空树
  2. 非空:根节点,根节点的左子树、根节点的右子树组成的

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

2. 二叉树的遍历

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

学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。

按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历

  1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。
  2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。
  3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。

由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。

// 二叉树前序遍历
void PrevOrder(BTNode* root);
// 二叉树中序遍历
void InOrder(BTNode* root);
// 二叉树后序遍历
void PostOrder(BTNode* root);
void PrevOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}printf("%d ", root->val);PrevOrder(root->left);PrevOrder(root->right);
}void InOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}InOrder(root->left);printf("%d ", root->val);InOrder(root->right);
}void PostOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}PostOrder(root->left);PostOrder(root->right);printf("%d ", root->val);
}

下面主要分析前序递归遍历,中序与后序图解类似,大家可自己动手绘制。

前序遍历递归图解:

前序遍历结果:1 2 3 4 5 6

中序遍历结果:3 2 1 5 4 6

后序遍历结果:3 2 5 6 4 1

2.2 层序遍历

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

// 层序遍历
void LevelOrder(BTNode* root);
void LevelOrder(BTNode* root)
{Que q;QueueInit(&q);if (root)QueuePush(&q, root);while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);printf("%d ", front->val);if (front->left)QueuePush(&q, front->left);if (front->right)QueuePush(&q, front->right);QueuePop(&q);}printf("\n");QueueDestroy(&q);
}

3. 节点个数及高度等

// 二叉树节点个数
int TreeSize(BTNode* root);
// 二叉树叶子节点个数
int TreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int TreeKLevel(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* TreeFind(BTNode* root, int x);
// 二叉树的高度
int TreeHeight(BTNode* root);
int TreeSize(BTNode* root)
{return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}int TreeLeafSize(BTNode* root)
{if (root == NULL)return 0;if (root->left == NULL && root->right == NULL)return 1;return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}int TreeKLevel(BTNode* root, int k)
{assert(k > 0);if (root == NULL)return 0;if (k == 1)return 1;return TreeKLevel(root->left, k - 1) + TreeKLevel(root->right, k - 1);
}BTNode* TreeFind(BTNode* root, int x)
{if (root == NULL)return NULL;if (root->val == x)return root;BTNode* ret = NULL;ret = TreeFind(root->left, x);if (ret)return ret;ret = TreeFind(root->right, x);if (ret)return ret;return NULL;
}int TreeHeight(BTNode* root)
{if (root == NULL)return 0;return fmax(TreeHeight(root->left), TreeHeight(root->right)) + 1;
}

4. 二叉树的创建和销毁

// 手动构建二叉树
BTNode* BuyNode(int x);
// 二叉树销毁
void TreeDestroy(BTNode* root);
// 判断二叉树是否是完全二叉树
int TreeComplete(BTNode* root);
BTNode* BuyNode(int x)
{BTNode* node = (BTNode*)malloc(sizeof(BTNode));if (node == NULL){perror("malloc fail");exit(-1);}node->val = x;node->left = NULL;node->right = NULL;return node;
}void TreeDestroy(BTNode* root)
{if (root == NULL)return;TreeDestroy(root->left);TreeDestroy(root->right);free(root);
}int TreeComplete(BTNode* root)
{Que q;QueueInit(&q);if (root)QueuePush(&q, root);while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);if (front == NULL)break;QueuePush(&q, front->left);QueuePush(&q, front->right);QueuePop(&q);}// 已经遇到空节点,如果队列中后面的节点还有非空,就不是完全二叉树while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);if (front != NULL){QueueDestroy(&q);return false;}}QueueDestroy(&q);return true;
}

本文完

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

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

相关文章

区块链技术的飞跃: 2023年的数字革命

随着时代的推进和技术的不断创新,2023年成为区块链技术飞跃发展的一年。区块链,一个曾经只是数字货币领域的技术,现在已经逐渐渗透到各个行业,成为推动数字经济发展的重要力量。在这个数字革命的时代,我们探讨区块链技…

什么是存储服务器?

随着互联网的发展,越来越多的信息会在网络上暴露,所以企业就会更加重视数据,因此更加安全可靠的数据存储服务器受到了大多数人的信赖,今天就让小编带大家了解一下什么是存储服务器吧! 存储服务器的含义。存储服务器是…

代理IP端口是什么意思呢?

今天,咱们来聊聊一个小众但很有料的话题——代理IP端口,它可是你纵横互联网世界的好搭子哦! 首先,我们得先弄明白,代理IP端口是个啥? 代理IP端口就像是通往网络世界的门票,是你和代理服务器之间的桥梁。…

使用注解新开事务 @Transactional

使用注解新开事务 Transactional(propagation Propagation.REQUIRES_NEW)

使用Perl脚本编写爬虫程序的一些技术问题解答

网络爬虫是一种强大的工具,用于从互联网上收集和提取数据。Perl 作为一种功能强大的脚本语言,提供了丰富的工具和库,使得编写的爬虫程序变得简单而灵活。在使用的过程中大家会遇到一些问题,本文将通过问答方式,解答一些…

Jetson Orin NX 开发指南(6): VINS-Fusion-gpu 的编译和运行

一、前言 由于 Jetson 系列的开发板 CPU 性能不是很好,因此在处理图像数据时往往需要 GPU 加速,而 VINS-Fusion 是针对同步定位与建图(SLAM)问题中十分出色的视觉算法,但是其在图像处理过程中资源消耗较大&#xff0c…

执行make menuconfig问题的解决

执行make menuconfig 出现问题 在终端输入以下命令执行。 make menuconfig在终端输入上面命令执行时,没有成功运行,出现了如下的问题。 出现这个错误提示意味着在运行 make menuconfig 命令时,系统找不到 ncurses 库。ncurses 是一种文本用…

iPhone手机记笔记工具选择用哪个

iPhone手机大家应该都比较熟悉,其使用性能是比较流畅的,在iPhone手机上记录笔记可以帮助大家快速地进行总结工作、记录工作内容等,在iPhone手机上记笔记工具选择用哪个呢? 可以在iPhone手机上使用的笔记工具是比较多的&#xff0…

Vue3中使用tinymce全功能演示,包括开源功能

效果图: 1、下载插件: npm i tinymce npm i tinymce/tinymce-vue 2、在node_modules文件夹中找到tinymce下的skins复制到项目public文件夹中 (可以先创建一个tinymce文件夹): 3、在tinymce官网中下载中文包,并放在刚…

FISCO BCOS | 构建第一个区块链应用程序

本章将介绍基于FISCO BCOS区块链的业务应用场景开发的全流程。介绍包括业务场景分析、合约设计实现、合约编译、区块链开发等。最后,我们介绍一个应用模块实现,即通过我们提供的Java SDK实现对区块链上合约的调用访问。 本教程要求用户熟悉Linux操作环境…

NCV6324CMTAATBG---车规级3MHz 2A 高效同步降压转换器

同步降压转换器? 是一种电源管理电路,它可以将输入电压转换为较低的输出电压。与传统的降压转换器相比,同步降压转换器具有更高的效率和更好的动态响应。 同步降压转换器的工作原理是通过控制开关管的导通和截止来实现电能的转换。在导通状…

Go语言入门心法(一)

一: go语言中变量认知 go语言中变量的定义: (要想飞|先会走)||(翻身仗|抹遗憾 )(1)go语言中变量认知升维(2)go语言中变量与强类型语言java类似,变量使用必须先声明后使用(3)go语言中变量标准的声明使用var关键字进行声明: var 变…

微信小程序通过 movable-area 做一个与vuedraggable相似的上下拖动排序控件

因为只是做个小案例 我就直接代码写page页面里了 其实很简单 组件稍微改一下就好了 wxss /* 设置movable-area的宽度 */ .area{width: 100%; }/* a b c 每条元素的样式 */ movable-view {width: 100%;background-color: red;height: 40px;line-height: 40px;color: #FFFFFF;tex…

如何进行pyhon的虚拟环境创建及管理

无论服务器或者本地,创建虚拟环境都是: 【Python】搭建虚拟环境_python创建虚拟环境_今天自洽了吗的博客-CSDN博客 虚拟环境绑定到项目 这个是运行环境,可以切换任意运行环境 如果是服务器上:可以先source xx/bin/active&#xf…

Python皮卡丘

系列文章 序号文章目录直达链接1浪漫520表白代码https://want595.blog.csdn.net/article/details/1306668812满屏表白代码https://want595.blog.csdn.net/article/details/1297945183跳动的爱心https://want595.blog.csdn.net/article/details/1295031234漂浮爱心https://want…

canvas基础2 -- 形状

七巧板 七巧板本质上就是 分别由几个直线 拼成一个个图形,再将这些图形结合起来 var tangram [{ p: [{ x: 0, y: 0 }, { x: 800, y: 0 }, { x: 400, y: 400 }], color: "#caff67" },{ p: [{ x: 0, y: 0 }, { x: 400, y: 400 }, { x: 0, y: 800 }], col…

1808_ChibiOS基本的架构介绍

全部学习汇总: GreyZhang/g_ChibiOS: I found a new RTOS called ChibiOS and it seems interesting! (github.com) 简单看了一下ChibiOS的架构介绍,感觉这种OS以及组件非常适合快速构建一个应用。这里做一个简单的资料整理。。 1. 不同于其他的OS&#…

JVM面试题:(三)GC和垃圾回收算法

GC: 垃圾回收算法: GC最基础的算法有三种: 标记 -清除算法、复制算法、标记-压缩算法,我们常用的垃圾回收器一般 都采用分代收集算法。 标记 -清除算法,“标记-清除”(Mark-Sweep)算法,如它的…

Vuex获取、修改参数值及异步数据处理

一、Vuex简介 1.1 vuex介绍 Vuex是专门为vue应用程序开发的状态管理模式,将组件的共享状态抽取出来,以一个全局单例模式进行管理,组件树构成一个巨大的视图,不管组件在树的何种位置,任何组件都能获取到状态和触发行为…

个股期权、商品期权、股指期权开户攻略(全网最全)

在进行个股期权、商品期权、股指期权交易之前,首先需要选择一个可靠的期权分仓平台。这样才能是想零门槛开通期权账户和交易权限,下文详细为大家科普个股期权、商品期权、股指期权开户攻略(全网最全) 一、期权分仓平台的选择 目前…