C语言数据结构初阶(10)----二叉树的实现

这篇具有很好参考价值的文章主要介绍了C语言数据结构初阶(10)----二叉树的实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

· CSDN的uu们,大家好。这里是C语言数据结构的第十讲。
· 目标:前路坎坷,披荆斩棘,扶摇直上。
· 博客主页: @姬如祎
· 收录专栏: 数据结构与算法

C语言数据结构初阶(10)----二叉树的实现 

 

目录

1. 函数接口一览

2. 函数接口的实现

2.1 BTNode* BuyNode(BTDataType x) 的实现

2.2 BTNode* CreateTree() 的实现

 2.3 void TreeDestroy(BTNode* root) 的实现

2.4 void PrevOrder(BTNode* root) 的实现

2.5 void InOrder(BTNode* root) 的实现

2.6 void PostOrder(BTNode* root) 的实现

2.7 void LevelOrder(BTNode* root) 的实现

2.7 int TreeSize(BTNode* root) 的实现

2.8 int TreeHeight(BTNode* root) 的实现

2.9 int TreeLevel(BTNode* root, int k) 的实现

 2.10 BTNode* TreeFind(BTNode* root, BTDataType x) 的实现

说明:因为是数据结构初阶,所以二叉树的创建方式我们选择直接开辟节点,然后手动链接。二叉树真正的创建方式在高阶的数据结构再来实现。因为我们实现的二叉树只是普通的二叉树,增删改查没有什么意义。像哪些特殊的二叉树,红黑树等的增删改查才有意义。这里这是通过常见接口的讲解来理解二叉树递归的性质。

1. 函数接口一览


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

//开辟一个节点
BTNode* BuyNode(BTDataType x);

//二叉树的手动创建
BTNode* CreateTree();

//二叉树的销毁
void TreeDestroy(BTNode* root);

//二叉树的前序遍历
void PrevOrder(BTNode* root);

//二叉树的中序遍历
void InOrder(BTNode* root);

//二叉树的后序遍历
void PostOrder(BTNode* root);

//二叉树的层序遍历
void LevelOrder(BTNode* root);

//二叉树的节点个数
int TreeSize(BTNode* root);

//二叉树的深度
int TreeHeight(BTNode* root);

//二叉树第K层的节点个数
int TreeLevel(BTNode* root, int k);

//二叉树查找节点值为X的节点
BTNode* TreeFind(BTNode* root, BTDataType x);

2. 函数接口的实现

2.1 BTNode* BuyNode(BTDataType x) 的实现

这个函数和链表中申请节点的作用相同,均是为了方便构建数据结构。在向堆区申请空间后需要将该节点的左右孩子的指针初始化为NULL。

//开辟一个节点
BTNode* BuyNode(BTDataType x)
{
	//堆区开辟节点
	BTNode* newNode = (BTNode*)malloc(sizeof(BTNode));
	if (newNode == NULL)
	{
		perror("BuyNode::malloc");
		exit(-1);
	}
	else
	{
		//节点初始化
		newNode->data = x;
		newNode->left = NULL;
		newNode->right = NULL;
		return newNode;
	}
}

2.2 BTNode* CreateTree() 的实现

文章开头我们就说明了,我们学的是最普通的二叉树,因此为了 方便起见,我们选择手动进行二叉树的构建。方法很简单,你只需要开辟你所需要构建的树的节点个数,然后将指针链接起来即可。这里我们构建一颗如下图所示的完全二叉树。

C语言数据结构初阶(10)----二叉树的实现

//二叉树的手动创建
BTNode* CreateTree()
{
	BTNode* node1 = BuyNode(1);
	BTNode* node2 = BuyNode(2);
	BTNode* node3 = BuyNode(3);
	BTNode* node4 = BuyNode(4);
	BTNode* node5 = BuyNode(5);
	BTNode* node6 = BuyNode(6);
	BTNode* node7 = BuyNode(7);
	BTNode* node8 = BuyNode(8);
	BTNode* node9 = BuyNode(9);

	node1->left = node2;
	node1->right = node3;

	node2->left = node4;
	node2->right = node5;

	node3->left = node6;
	node3->right = node7;

	node4->left = node8;
	node4->right = node9;

	return node1;
}

 2.3 void TreeDestroy(BTNode* root) 的实现

二叉树的初阶内容不涉及数据的增删改查,我们学习的主要内容就是理解二叉树的递归特性。为将来学习特殊的二叉树打好基础。因此下面开始的函数均选择使用递归来实现。

这个函数的实现比较简单,但是释放节点的顺序还是有讲究的,如下图,我们要对这三个节点进行释放,我们有三个选择:先释放4;先释放8;先释放9。显然我们不会选择先释放4,因为如果你想要先释放4,那么你还需要用变量先保存4的左右孩子,这样就显得比较麻烦啦。至于是先释放8.还是先释放9,就没有优劣之差啦。

C语言数据结构初阶(10)----二叉树的实现

 在释放树的节点时,显然只能从叶子节点开始释放,这恰恰符合了递归递去归来的特性,因此我们选择使用递归来实现。通过递归,先到达叶子节点,我们不妨先释放左孩子,再释放右孩子,如果左右孩子不为空,我们就释放他们,然后再释放左右孩子的双亲节点,释放完成后逐步向上返回,直到将根结点释放。下图展示了8这个节点的销毁过程,请结合代码进行理解。

C语言数据结构初阶(10)----二叉树的实现

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

	free(root);
	root = NULL;
}

2.4 void PrevOrder(BTNode* root) 的实现

 前序遍历,就是在遍历二叉树时先访问根结点,在访问左子树,最后访问右子树。二叉树的递归逻辑都是相似的,可以结合下面的这张图来理解前序遍历。

C语言数据结构初阶(10)----二叉树的实现

 在进行前序遍历的时候,他的本质是会去访问叶子节点左右孩子的那两个NULL指针的,因此在访问到NULL时,我们可以将NULL打印出来,这样能更加深刻的理解前序遍历的本质。

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

}

2.5 void InOrder(BTNode* root) 的实现

中序遍历就是在遍历二叉树的时候先访问左子树,再访问根结点,最后访问右子树。思路就是二叉树的递归思路,代码只需要将前序遍历代码的顺序交换一下即可。

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

}

2.6 void PostOrder(BTNode* root) 的实现

后续遍历就是指在遍历二叉树时先访问左子树,再访问右子树,最后访问根结点。

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

}

2.7 void LevelOrder(BTNode* root) 的实现

层序遍历就是将一棵树按照每一层每一层的方式进行遍历,下图中的二叉树的层序遍历结果就是:1 2 3 4 5 6 7 8 9

C语言数据结构初阶(10)----二叉树的实现

这该怎么做呢?其实很简单,我们只需要维护一个队列, 一开始呢,先将根结点入队列。然后进入一个循环,循环继续的条件就是队列不为空,然后逐步取出队头的元素,如果队头元素的左右孩子有不为空的,就将其入队列,依次类推,节点从队列中出来的顺序就是层序遍历的结果。

C语言数据结构初阶(10)----二叉树的实现

至于队列的选择,我们选择使用数组模拟实现队列,因为C语言嘛,不像其他语言那么方便。

关于数组模拟实现队列,请参考:数据模拟实现队列

2.7 int TreeSize(BTNode* root) 的实现

你可能会想,我们维护一个变量Size,然后将二叉树遍历一遍,每遍历到一个节点就将Size++,这样就能求出二叉树的节点个数了。这没问题,很好,只不过这种方法有一点值得注意,如果你不使用全局或者静态变量,而是将Size作为参数传递给TreeSize函数,那么,一定记得传指针哦!具体原因想必大家都懂啦!俺们都是C语言学完的人了!但是这里不推荐使用全局和静态的变量。如果你要对多棵树调用该方法,那么你还得重新初始化这个全局变量,比较麻烦。

这里我们就不对上面的这种方法做实现啦!这里还有一种方法:整个二叉树节点的个数就等于左子树节点的个数 + 右子树节点的个数 + 1 (这个1就是根节点啦)。这便是分治思想。将大的问题拆解成小的问题(说实话还有一点动态规划的味道)。

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

2.8 int TreeHeight(BTNode* root) 的实现

我们理解了求解TreeSize的思路,TreeHeight就是信手拈来的事情。同样地,我们利用分治的思想:树的深度 = 左右子树中深度较大的那一个 + 1,是不是很简单嘞。

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

2.9 int TreeLevel(BTNode* root, int k) 的实现

求解二叉树第K层的节点个数,怎么用分治的思想解决呢?上图解

C语言数据结构初阶(10)----二叉树的实现

 这下是不是有思路了呢?当我们递归到所求节点总数的那一层时,对于K = 1,而这个时候呢,我们就不要向下递归啦!这层有节点的话,递归到此层的每一个节点返回1就行啦!

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

 2.10 BTNode* TreeFind(BTNode* root, BTDataType x) 的实现

咦,不是说普通的二叉树不学增删改查吗!哈哈,勉强看一个吧,这里有一个地方值得注意,TreeFind函数的返回值不是bool值而是查找到的节点,如果有修改的需要,我们就能够在查找的同时对节点的值进行修改啦!是不是很方便。

怎么实现这个函数呢?其实很简单,我们先对每一层递归的根结点进行判断,如果这个时候根结点的data就等于x那么直接返回结果就行。如果根结点的data值不等于x呢?

我们就在根结点的左子树中去找,也就是往左子树递归、如果在左子树找的结果不为空,说明在左子树中找到了data值为x的节点,返回该节点即可!

如果左子树没找到,就在右子树中去找,也就是往右子树去递归。如果在右子树找的结果不为空,说明在右子树中找到了data值为x的节点,返回该节点即可!如果在右子树中没有找到嘞,说明左右子树都没找到,返回NULL即可。

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

	BTNode* right = TreeFind(root->right, x);
	if (right)
		return right;
	
	return NULL;
}

C语言数据结构初阶(10)----二叉树的实现文章来源地址https://www.toymoban.com/news/detail-402740.html

到了这里,关于C语言数据结构初阶(10)----二叉树的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【初阶数据结构】树结构与二叉树的基础概念

    君兮_的个人主页 勤时当勉励 岁月不待人 C/C++ 游戏开发 Hello,米娜桑们,这里是君兮_,今天带来数据结构里的重点内容也是在笔试,面试中的常见考点——树与二叉树,其中二叉树又分为很多种,我们先来讲讲基础的内容带大家一步步入门 在介绍二叉树之前,我们得先知道什

    2024年02月08日
    浏览(31)
  • 数据结构初阶之二叉树的详细解析

    个人主页:点我进入主页 专栏分类:C语言初阶      C语言程序设计————KTV       C语言小游戏     C语言进阶 C语言刷题       数据结构初阶    Linux 欢迎大家点赞,评论,收藏。 一起努力,共赴大厂。 目录 1.前言  2.二叉树各个功能代码实现 2.1二叉树结构体 2.2二叉

    2024年02月05日
    浏览(27)
  • 【初阶数据结构】二叉树的几种遍历详解

    君兮_的个人主页 勤时当勉励 岁月不待人 C/C++ 游戏开发 Hello,米娜桑们,这里是君兮_,有了我们之前介绍的树结构与二叉树的基础概念,今天我们来讲讲对二叉树的基本使用——遍历 我们自己先简单链式连接几个结点来创建一个二叉树方便我们之后对遍历的讲解 好了,有了

    2024年02月08日
    浏览(33)
  • 初阶数据结构之---二叉树链式结构(二叉树的构建,二叉树的前序,中序,后序和层序遍历,计算二叉树结点个数,第k层结点个数,叶子结点个数,判断是否为完全二叉树)

    本篇博客是初阶数据结构树的收尾,将会讲掉 基本二叉树链式结构的具体内容和实现,包括二叉树的构建,前序遍历,中序遍历,后序遍历和层序遍历,计算二叉树结点个数,第k层结点个数,二叉树叶子结点个数,以及判断一个二叉树是否为完全二叉树 。话不多说,开始我

    2024年03月24日
    浏览(37)
  • 二叉树的实现(C语言数据结构)

    目录 一、以下是我们需要实现的功能 二、以下是我们具体功能的实现 1.创建新的结点 2.通过数组生成二叉树  3.先序遍历 4.中序遍历 5.后序遍历   6.层序遍历 7.计算二叉树的结点个数 8.查找指定值为x的结点 9.查找第K层的结点个数 10.统计二叉树叶子结点的个数 11.判断是否为

    2024年02月04日
    浏览(28)
  • 【C语言 数据结构】二叉树的遍历

    所谓先序遍历二叉树,指的是从根结点出发,按照以下步骤访问二叉树的每个结点: 访问当前结点; 进入当前结点的左子树,以同样的步骤遍历左子树中的结点; 遍历完当前结点的左子树后,再进入它的右子树,以同样的步骤遍历右子树中的结点; 先序遍历这棵二叉树的过

    2024年02月04日
    浏览(33)
  • 数据结构初阶之基础二叉树(C语言实现)

    📃 博客主页: 小镇敲码人 💞 热门专栏:数据结构与算法 🚀 欢迎关注:👍点赞 👂🏽留言 😍收藏 🌏 任尔江湖满血骨,我自踏雪寻梅香。 万千浮云遮碧月,独傲天下百坚强。 男儿应有龙腾志,盖世一意转洪荒。 莫使此生无痕度,终归人间一捧黄。🍎🍎🍎 ❤️ 什么

    2024年03月19日
    浏览(32)
  • 二叉树的基本操作-C语言实现-数据结构作业

    目录  (1)二叉树的创建; (2)二叉树的先序、中序和后序遍历输出; (3)输出二叉树的叶子节点和度为2的节点的数量; (4)输出二叉树的深度; (5)将二叉树所有节点的左右子树互换(左子树变右子树,右子树变左子树); (6)参考书上,二叉树按层次输出(一行输出一层); (7)删除二

    2024年02月04日
    浏览(34)
  • 【数据结构】二叉树的前中后序遍历(C语言)

    [二叉树] 顾名思义就是有 两个分支节点的树,不仅如此,除了叶子外的所有节点都具有两个分支节点; 由于结构像一棵倒立的树,顾名思义为二叉树 ; 如下图所示,该图即为一棵 野生的二叉树 ; 既然二叉树为树,固然有着和树一样的部分( 叶子、根、分支… ) 这些也成为

    2024年02月17日
    浏览(33)
  • 数据结构实验报告,二叉树的基本操作(C语言)

    作者:命运之光 专栏:数据结构 实验六 二叉树的基本操作 实验环境:Visual C++或Dev C++ 实验目的: 1、掌握二叉树创建; 2、掌握二叉树的遍历及常用算法。 实验内容: 通过完全前序序列创建一棵二叉树,完成如下功能: 1)输出二叉树的前序遍历序列; 2)输出二叉树的中序遍

    2024年02月09日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包