二叉树的实现用链表(符原码)

二叉树的表示方法

通常的⽅法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别⽤来给出该结点左孩⼦和右孩⼦所在的链结点的存储地址。

结构如下:

typedef int BTDataType;
// ⼆叉链
typedef struct BinaryTreeNode
{
 struct BinTreeNode* left; // 指向当前结点左孩⼦ 
 struct BinTreeNode* right; // 指向当前结点右孩⼦ 
 BTDataType val; // 当前结点值域 
}BTNode;

实现链式二叉树的方法

二叉树主要分为,空树和非空树,非空树主要是由节点,根节点左子树,根节点右子树组成的,实现链式二叉树可以运用递归进行代码的编写。二叉树的遍历方式分为,先序遍历(根节点,左子树,右子树),中序遍历(左子树,根节点,右子树),后续遍历(左子树,右子树,根节点)这三种遍历的方式。

遍历方式的练习

1.设⼀棵 ⼆叉树的中序遍历序列:badce,后序遍历序列:bdeca,则⼆叉树前序遍历序列为____

例题一解析

2.某⼆叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出(同⼀层从左到右) 的序列为___。  

例二解析

 二叉树的递归调用

二叉树的链式访问,运用的是递归,在这里我们可以体会到递归的美学,下面我们通过示意图进行具体的解释。

前序遍历,中序遍历,后续遍历基本思想都是运用了这张图所展现的思想就说递归,所以不足具体的解析了。

二叉树递归的示意图

 二叉树求k层节点的个数求解分析:求k层节点的个数这里面其实我开始也是不知道如何表示取到k层的,这里运用了图像进行了讲解。

 二叉树深度求解分析:

⼆叉树查找值为x的结点分析:

 层序遍历:

 二叉树的销毁:

 

源代码

tree.h

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef struct BinaryTree
{
	int data;
	struct BinaryTree *left;
	struct BinaryTree* right;
}tree;
//树的先序遍历
void PreOrder(tree* root);
//中序遍历
void InOrder(tree* root);
//后序遍历 
void PostOrder(tree* root);
//树的销毁
void TreeDestory(tree* root);
//计算树的总节点个数
int TreeSize(tree* root);
//计算树叶子节点的个数
int TreeLeafSize(tree * root);
// ⼆叉树第k层结点个数
int TreeLevelKSize(tree* root, int k);
//⼆叉树的深度/⾼度
int TreeDepth(tree* root);
// ⼆叉树查找值为x的结点
tree* TreeFind(tree* root, int x);
// ⼆叉树销毁
void TreeDestory(tree** root);
//层序遍历
void LevelOrder(tree* root);
//判断二叉树是否为完全二叉树
bool TreeComplete(tree* root);

tree.c

#include"tree.h"
// 树的先序遍历
void PreOrder(tree* root)
{
	if (root == NULL)
	{
		return;
	}
	printf("%d", root->data);
	PreOrder(root->left);
	PreOrder(root->right);
}
// 树的中序遍历
void InOrder(tree* root)
{
	if (root == NULL)
	{
		return;
	}
	InOrder(root->left);
	printf("%d", root->data);
	InOrder(root->right);
}
// 树的后序遍历
void PostOrder(tree* root)
{
	if (root == NULL)
	{
		return;
	}
	PostOrder(root->left);
	PostOrder(root->right);
	printf("%d", root->data);
}
//计算树的总节点个数
int TreeSize(tree* root)
{
	if (root == NULL)
	{
		return 0;
	}
	return 1 + TreeSize(root->left) + TreeSize(root->right);
}
//计算树叶子节点的个数
int TreeLeafSize(tree* root)
{
	if (root == NULL)
	{
		return 0;
	}
	//当某一个节点是下一个的左右两侧都为NULL时就可证明此时就是叶子节点
	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	return TreeLeafSize(root->left)+ TreeLeafSize(root->right);
}
// ⼆叉树第k层结点个数
int TreeLevelKSize(tree* root, int k)
{
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	return TreeLevelKSize(root->left, k - 1) + TreeLevelKSize(root->right, k - 1);
}
//⼆叉树的深度/⾼度
int TreeDepth(tree* root)
{
	if (root == NULL)
	{
		return 0;
	}
	int LeftDepth = TreeDepth(root->left);
	int RightDepth = TreeDepth(root->right);
	return LeftDepth > RightDepth ? LeftDepth + 1 : RightDepth + 1;
}
// ⼆叉树查找值为x的结点
tree* TreeFind(tree* root, int x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->data == x)
	{
		return root;
	}
	tree* leftFind = TreeFind(root->left, x);
	if (leftFind)
	{
		return leftFind;
	}
	tree* rightFind = TreeFind(root->right, x);

	if (rightFind)
	{
		return rightFind;
	}
	return NULL;
}
// ⼆叉树销毁
void TreeDestory(tree** root)
{
	if (*root == NULL)
	{
		return;
	}
	//注意这里的传参
	TreeDestory(&((*root)->left));
	TreeDestory(&((*root)->right));
	free(*root);
	*root = NULL;
}
//层序遍历
void LevelOrder(tree* root)
{
	Qu q;
	QueueInit(&q);
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		//取队头,打印
		tree* front = QueueFront(&q);
		printf("%d ", front->data);
		QueuePop(&q);
		//队头节点的左右孩子入队列
		if (front->left)
			QueuePush(&q, front->left);
		if (front->right)
			QueuePush(&q, front->right);
	}
	//队列为空
	QueueDestroy(&q);
}
//判断二叉树是否为完全二叉树
bool TreeComplete(tree* root)
{

}

test.c

#include"tree.h"
tree* buyNode(int x)
{
	tree* newnode = (tree*)malloc(sizeof(tree));
	if (newnode == NULL)
	{
		perror("malloc fail!");
		exit(1);
	}
	newnode->data = x;
	newnode->left = newnode->right = NULL;

	return newnode;
}

void test01()
{
	tree* node1 = buyNode(1);
	tree* node2 = buyNode(2);
	tree* node3 = buyNode(3);
	tree* node4 = buyNode(4);
	node1->left = node2;
	node1->right = node3;
	node2->right = node4;
	


	PreOrder(node1);
	printf("\n");

	InOrder(node1);
	printf("\n");

	PostOrder(node1);
	printf("\n");

	printf("size:%d\n", TreeSize(node1));
	printf("leaf size: %d\n", TreeLeafSize(node1));
	printf("第K层size : %d\n", TreeLevelKSize(node1, 3));
	printf("depth/height:%d\n", TreeDepth(node1));

	tree* find =TreeFind(node1, 6);
	printf("%s\n", find == NULL ? "未找到!" : "找到了!");

	TreeDestory(&node1);
}

int main()
{
	test01();
	return 0;
}

总结

链式二叉树在计算机科学中有广泛的应用,例如在搜索算法、排序算法、表达式求值、图算法等领域。链式二叉树使用递归是非常方便的,但是我们不要忘记递归一定要有限制条件,不然递归就说无限制循环了。最后创作不易希望各位大佬可以留下珍贵的一键三连(点赞,收藏,关注)。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值