二叉树--C语言实现数据结构

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

二叉树--C语言实现数据结构,数据结构,c语言,数据结构,开发语言,学习,算法

本期带大家一起用C语言实现二叉树🌈🌈🌈

1、二叉树的定义

二叉树是一种特殊的树状数据结构,它由节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点

二叉树的链式存储结构是指用 链表 来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三

个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址

2、二叉树 的结构

二叉树--C语言实现数据结构,数据结构,c语言,数据结构,开发语言,学习,算法

3、二叉树的实现

3.1 结构设计

typedef int BTreeDataType;

typedef struct BTreeNode
{
	BTreeDataType val;

	struct BTreeNode* right;
	struct BTreeNode* left;
}BTNode;

3.2 手动构建二叉树

二叉树--C语言实现数据结构,数据结构,c语言,数据结构,开发语言,学习,算法

BTNode* CreatNode(BTreeDataType val)
{
	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	if (root == NULL)
	{
		perror("root malloc fail");
		return;
	}

	root->val = val;
	root->left = NULL;
	root->right = NULL;

	return root;

}
BTNode* CreatBinaryTree()
{
	
	BTNode* root1 = CreatNode(1);
	BTNode* root2 = CreatNode(2);
	BTNode* root3 = CreatNode(3);
	BTNode* root4 = CreatNode(4);
	BTNode* root5 = CreatNode(5);
	BTNode* root6 = CreatNode(6);
	BTNode* root7 = CreatNode(7);

	root1->left = root2;
	root1->right = root3;
	root2->left = root4;
	root2->right = root5;
	root3->left = root6;
	root3->right = root7;
	return root1;

}

3.3 前序遍历

  1. 首先进行条件判断,如果当前节点root为空,即遍历到了空节点,输出"N "(表示Null)之后返回。这是因为在先序遍历中,空节点也需要被遍历到。

  2. 若当前节点root不为空,则输出当前节点的值root->val

  3. 继续递归遍历当前节点的左子树,即调用PrevOrder(root->left)

  4. 最后,递归遍历当前节点的右子树,即调用PrevOrder(root->right)

通过递归的方式,先序遍历会按照先根节点、左子树、右子树的顺序遍历整个二叉树。在代码中,先打印当前节点的值,然后分别遍历左子树和右子树。

void PrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	else
		printf("%d ", root->val);
	PrevOrder(root->left);
	PrevOrder(root->right);

}

二叉树--C语言实现数据结构,数据结构,c语言,数据结构,开发语言,学习,算法

3.4 中序遍历

  1. 首先进行条件判断,如果当前节点root为空,即遍历到了空节点,输出"N "(表示Null)之后返回。这是因为在中序遍历中,空节点也需要被遍历到。

  2. 若当前节点root不为空,则递归遍历当前节点的左子树,即调用InOrder(root->left)

  3. 输出当前节点的值root->val

  4. 最后,递归遍历当前节点的右子树,即调用InOrder(root->right)

通过递归的方式,中序遍历会按照左子树、根节点、右子树的顺序遍历整个二叉树。在代码中,先遍历左子树,然后打印当前节点的值,最后遍历右子树。这样可以保证中序遍历的顺序性。

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

}

3.5 后序遍历

后序遍历的访问次序是 先访问左子树,再访问右子树,再访问根节点

逻辑同前序遍历和中序遍历差不多

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

}

3.4 层序遍历

层序遍历就是从第一层开始从左向右逐个遍历

那么当前结果就是1 2 3 4 5 6 7

层序遍历的话,需要一个队列来进行辅助

首先我们将root根节点放进去,然后判断队列当中是否为空,为空就跳出循环

不为空的话就将节点不为NULL的放进去,直到队列为空

void LevalOrder(BTNode* root)
{
	if (root == NULL)
		return;
	Queue q;
	QueueInit(&q);
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		printf("%d ", front->val);
		if(front->left)
			QueuePush(&q, front->left);
		if(front->right)
			QueuePush(&q, front->right);

	}

	QueueDestroy(&q);

}

核心思想就是出上一层带下一层

3.5 计算二叉树的节点数

这里我们可以有两种思路:
1、给定一个 size ,遍历二叉树,分别遍历左右子树,遍历过程中遍历到非空节点 size++,遍历到空,则返回 0。
2、二叉树的大小 = 根节点 + 左子树节点 + 右子树节点,将其分成多个子问题,递归求解。

思路1 size计数

使用局部变量size来记录节点数量是不可行的。因为在递归调用的过程中,每一次递归都会创建一个新的函数栈帧,这意味着每个递归调用都有自己独立的size变量,并且初始值都是0,无法准确计算出二叉树的大小。

为了解决这个问题,可以使用全局变量size来记录节点数量。全局变量位于全局数据区,在整个工程内都有效。但需要注意的是,由于全局变量不会被销毁,如果多次调用计算节点数量的函数,size会累加,可能导致错误的结果。因此,在每次调用之前,需要将size重置为0,以确保准确计算二叉树的大小。

总结来说,局部变量不能满足统计二叉树节点数量的在这里插入代码片需求,需要使用全局变量,并在每次调用之前将其重置为0。

int size = 0;

int BTreeSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	size++;
	BTreeSize(root->left);
	BTreeSize(root->right);
	return size;
}

思路2 递归实现
计算二叉树的节点数

如果root==NULL的话,那我们就返回0

不然的话我们就返回1+左子树的节点树+右子树的节点数

int BTreeSize(BTNode* root)
{

	//return root == NULL ? 0 : 1 + BTreeSize(root->left) + BTreeSize(root->right);

	if (root == NULL)
		return 0;

	return 1 + BTreeSize(root->left) + BTreeSize(root->right);
}

3.6 计算二叉树的高度

计算二叉树的高度

如果我们的root==NULL的话,那我们返回0

不然的话计算左子树的高度和右子树的高度

让最高的子树高度+1就是我们的二叉树高度

不过需要注意的是需要拿left_height和right_height来计数,防止重复递归调用

不然到时候还得重复计算好多次,尤其是会重复计算下面的高度

可不是简单的二倍关系

nt BTreeHeight(BTNode* root)
{
	if (root == NULL)

		return 0;
	int left_hight = BTreeHeight(root->left);
	int right_hight = BTreeHeight(root->right);

	return left_hight > right_hight ?  1 + left_hight : 1 + right_hight;
}

3.7 计算叶子节点的个数

计算叶子节点的个数

如果root==NULL,返回0

如果root->left == NULL && root->right == NULL 那就返回1

如果还不满足以上的条件话,那就返回左子树的叶子节点个数+右子树叶子节点个数

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


}

3.8 计算第K层节点数

计算第K层节点数

对于第一层,需要计算的是 第 k 层的节点个数;
对于第二层,需要计算的是 第 k - 1 层的节点个数;
对于第 k 层,计算的就是 第 1 层( 当前层数 ) 的节点个数。

如果我的root==NULL的话,那就返回0

如果我的root!=NULL而且k==1的话那就返回1

不然的话就返回左子树第k-1层节点的数目+右子树第k-1层节点的数目

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

}

3.9 查找某个值对应的节点

查找某个值对应的节点

如果root==NULL,返回NULL

如果root->val==val,返回root

既然root->val!=val,那么就去左右子树分别查找

如果在左子树查走到了,那么就返回左子树当中找到的那个节点

如果在右子树查走到了,那么就返回右子树当中找到的那个节点

至于为什么要判断左右子树查找到结果不为NULL呢

因为左子树如果结果是NULL,不然直接返回NULL

还有右子树没有查找

右子树的结果的话可以不用判NULL,因为这个时候根节点和左子树当中都没有找到val,那么就剩下右子树了

如果右子树还没有的话,那就没有,返回NULL,有的话就返回节点

BTNode* BTreeFind(BTNode* root, BTreeDataType val)
{
	if (root == NULL)
		return NULL;
	if (root->val == val)
		return root;
	BTNode* leftNode = BTreeFind(root->left,val);
	if (leftNode != NULL)
		return leftNode;
	BTNode* rightNode = BTreeFind(root->right, val);
	if (rightNode != NULL)
		return rightNode;
	return NULL;

}

3.10 判断是否为满二叉树

和层序遍历的思想一样,需要一个队列来进行辅助

首先将根节点root放到队列当中
如果在中途遇到了NULL的话,那就跳出循环
如果没遇到NULL的话,那就带下一层子树进来

遇到NULL结束入队列,并且检查队列当中是否还有有效元素(NULL除外)

如果全是NULL,那就代表这个二叉树完全二叉树

不然的话就不是

bool IsComplete(BTNode* root)
{
	Queue q;

	QueueInit(&q);
	
	if(root)
	QueuePush(&q, root);
	
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front == NULL)
			break;
		QueuePush(&q, front->left);
		QueuePush(&q, front->right);
	}
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front != NULL)
		{
			QueueDestroy(&q);
			return false;
		}

	}
	QueueDestroy(&q);
	return true;
}

3.11 二叉树的销毁

二叉树的销毁逻辑是和后序遍历一样的

void BTreeDestroy(BTNode* root)
{

	if (root == NULL)
		return;
	BTreeDestroy(root->left);
	
	BTreeDestroy(root->right);

	free(root);

}

4、感谢与交流✅

🌹🌹🌹如果大家通过本篇博客收获了,对二叉树有了新的了解的话
那么希望支持一下哦如果还有不明白的,疑惑的话,或者什么比较好的建议的话,可以发到评论区,
我们一起解决,共同进步 ❗️❗️❗️
最后谢谢大家❗️❗️❗️💯💯💯

二叉树--C语言实现数据结构,数据结构,c语言,数据结构,开发语言,学习,算法文章来源地址https://www.toymoban.com/news/detail-581964.html

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

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

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

相关文章

  • 数据结构(C语言实现)——二叉树的概念及二叉树顺序结构和链式结构的实现(堆排序+TOP-K问题+链式二叉树相关操作)

    前面学习了数据结构中线性结构的几种结构,顺序表,链表,栈和队列等,今天我们来学习一种非线性的数据结构——树。由于二叉树是数据结构中的一个重点和难点,所以本文着重介绍二叉树的相关概念和性质,以及二叉树的应用。 树是一种非线性的数据结构,它是由n(

    2023年04月21日
    浏览(45)
  • C语言数据结构初阶(10)----二叉树的实现

    · CSDN的uu们,大家好。这里是C语言数据结构的第十讲。 · 目标:前路坎坷,披荆斩棘,扶摇直上。 · 博客主页: @姬如祎 · 收录专栏: 数据结构与算法     目录 1. 函数接口一览 2. 函数接口的实现 2.1 BTNode* BuyNode(BTDataType x) 的实现 2.2 BTNode* CreateTree() 的实现  2.3 void

    2023年04月08日
    浏览(44)
  • 二叉树的基本操作-C语言实现-数据结构作业

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

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

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

    2024年03月19日
    浏览(43)
  • 【数据结构】线索二叉树(适用场景+图文推导过程+C语言代码实现)

    普通二叉树(如下图): 空间浪费 :存在大量“∧”,该空间未利用。 时间效率 :查找一次结点的前驱、后继就需要遍历一次,时间效率低。         在实际问题中,如果所用的 二叉树需经常遍历或查找结点时需要某种遍历序列中的前驱和后继,那么采用线索二叉链表

    2024年02月04日
    浏览(37)
  • 数据结构入门(C语言版)二叉树的顺序结构及堆的概念及结构实现应用

    普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用 顺序结构的数组来存储 ,需要注意的是 这里的堆和操作系统虚拟进程地址空间中的堆是两回事 ,一个是 数据结构 ,一

    2023年04月19日
    浏览(53)
  • 【数据结构初阶】七、非线性表里的二叉树(堆的实现 -- C语言顺序结构)

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【数据结构初阶】六、线性表中的队列(链式结构实现队列)-CSDN博客  ===========================

    2024年02月08日
    浏览(45)
  • [C语言实现]数据结构堆之《害怕二叉树所以天赋全点到堆上了》

    🥰作者: FlashRider 🌏专栏: 数据结构 🍖知识概要:详解 堆 的概念、小根堆与大根堆的区别、以及代码实现。 目录 什么是堆? 如何实现堆? 代码实现堆(小根堆) 定义堆以及堆的初始化和销毁。 堆的插入 堆的删除 获取堆的元素长度和获取堆顶元素 代码测试 TopK问题 我们先

    2024年02月09日
    浏览(35)
  • 数据结构---二叉树(C语言)

    空树 非空:根节点,根节点的左子树、根节点的右子树组成的。 从二叉树的定义来看,二叉树是递归定义的,因此我们可以用递归的形式来遍历二叉树。 1.1.1二叉树前中后序遍历(递归版) 访问根结点的顺序不同。 1.1.2 层序遍历 层序遍历是按照二叉树的高度,一层一层遍

    2024年02月06日
    浏览(47)
  • 【数据结构】二叉树---C语言版

    树是一种 非线性 的数据结构,它是由n(n=0)个有限结点组成一个具有层次关系的集合。把它叫做树,是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。 有一个特殊的结点,称为根结点, 根节点没有前驱结点 除根节点外,其余结点被分成M(M0)个互不相交

    2024年02月05日
    浏览(44)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包