您现在的位置是:首页 >技术教程 >数据结构入门(C语言版)二叉树链式结构的实现网站首页技术教程

数据结构入门(C语言版)二叉树链式结构的实现

小谢爱学C语言 2023-05-26 00:00:02
简介数据结构入门(C语言版)二叉树链式结构的实现

在这里插入图片描述

二叉树的概念及结构创建

1、概念

简单回顾一下二叉树的概念:
★ 空树
★非空:根节点,根节点的左子树、根节点的右子树组成的。

在这里插入图片描述
在这里插入图片描述
从概念中可以看出,二叉树定义是递归式的,因此后序基本操作中基本都是按照该概念实现的。

2、结构创建

下面我们先看二叉树的结构体定义以及创建

typedef char BTDataType;
typedef struct BinaryTreeNode
{
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
	BTDataType data;
}BTNode;

首先结构体的定义是元素本身,以及左右子树的指针。

2、创建结点函数

BTNode* BuyNode(BTDataType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		printf("malloc fail
");
		exit(-1);
	}

	node->data = x;
	node->left = node->right = NULL;
	return node;
}

我们指定每调用一次此函数,便新建一个结点空间,并将左右指针指向空即可。

3、建树函数

BTNode* CreatBinaryTree()
{
	BTNode* nodeA = BuyNode('A');
	BTNode* nodeB = BuyNode('B');
	BTNode* nodeC = BuyNode('C');
	BTNode* nodeD = BuyNode('D');
	BTNode* nodeE = BuyNode('E');
	BTNode* nodeF = BuyNode('F');

	nodeA->left = nodeB;
	nodeA->right = nodeC;
	nodeB->left = nodeD;
	nodeC->left = nodeE;
	nodeC->right = nodeF;

	return nodeA;
}

这个函数是树建立的关键步骤,将每个结点创建完成后,再将每个结点的左右指针重定义,继而完成建树,上述代码执行后表示的就是下图:
在这里插入图片描述

二叉树的遍历

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

主要分为以下几种:

1、前序遍历

前序遍历(Preorder Traversal | 先序遍历)——访问根结点的操作发生在遍历其左右子树之前,顺序为:根 ->左子树->右子树
比如上面这个二叉树前序遍历输出为:
A B D NULL NULL NULL C E NULL NULL F NULL NULL
实现代码如下:

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

这个函数的实现是利用前序的性质,首先取根节点,之后每个结点先返回左结点,再返回右结点的顺序,进行递归调用,到最后的叶子结点之后再逐个返回打印输出,即为前序遍历。

2、中序遍历

中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中。
顺序为:左子树 ->根->右子树
比如这个二叉树中序遍历输出为:
NULL D NULL B NULL A NULL E NULL C NULL F NULL
实现代码如下:

void InOrder(BTNode* root)
{
	if (root == NULL){
		printf("NULL ");
		return;
	}

	InOrder(root->left);
	printf("%C ", root->data);
	InOrder(root->right);
}

中序遍历就是将前序稍微做调整,先打印左子树,再打印根,之后才是右子树,同样用的是递归分治。

3、后序遍历

后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。
顺序为:左子树 ->右子树->根
比如这个二叉树中序遍历输出为:
NULL NULL D NULL B NULL NULL E NULL NULL F C A
实现代码如下:

void PostOrder(BTNode* root)
{
	if (root == NULL){
		printf("NULL ");
		return;
	}

	PostOrder(root->left);
	PostOrder(root->right);
	printf("%C ", root->data);
}

此函数与上面两个同理而得。

4、层序遍历

除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
在这里插入图片描述
比如这个二叉树,层序遍历结果为123456。
代码实现如下:

void BinaryTreeLevelOrder(BTNode* root)
{
	if (root == NULL)
		return;

	Queue q;
	QueueInit(&q);
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		printf("%c ", front->data);

		if (front->left)
			QueuePush(&q, front->left);

		if (front->right)
			QueuePush(&q, front->right);
	}
	printf("
");

	QueueDestroy(&q);
}

因为是链式结构,这里的层序遍历采用队列来实现,不了解队列的小伙伴可以看看我之前的文章:栈和队列之队列的介绍及实现
首先我们建立一个队列,初始化后先入根,再出根打印,继续打印其左右结点,继而循环打印,直到为空终止,最后释放队列空间,完成层序遍历打印。

二叉树的销毁

代码如下:

void BinaryTreeDestory(BTNode* root)
{
	if (root == NULL)
	{
		return;
	}

	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	free(root);
}

销毁与前中后序的实现一样,使用递归自下而上销毁。

结语

有兴趣的小伙伴可以关注作者,如果觉得内容不错,请给个一键三连吧,蟹蟹你哟!!!
制作不易,如有不正之处敬请指出
感谢大家的来访,UU们的观看是我坚持下去的动力
在时间的催化剂下,让我们彼此都成为更优秀的人吧!!!

在这里插入图片描述

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。