首页 > 其他分享 >数据结构之链式二叉树

数据结构之链式二叉树

时间:2024-03-15 13:59:51浏览次数:28  
标签:左子 遍历 右子 访问 二叉树 链式 数据结构 root 节点

当我们初步了解二叉树后

我们就可以进一步去深入学习二叉树了

1.链式二叉树的遍历

这里我们先去定义链式二叉树的结构

分为两个指针

一左一右

他们分别指向左子树和右子树

typedef int BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinartTreeNode* left;
	struct BinartTreeNode* right;
}TreeNode;

左右子树的节点又可以细分为:根,左子树,右子树

图中的1节点就是根,2和3则是左子树,456则是右子树

1.1二叉树的前序,中序,后序遍历


前序遍历、中序遍历和后序遍历。这些遍历方式指的是节点访问的顺序。

前序遍历:在前序遍历中,我们首先访问根节点,然后递归地进行左子树的前序遍历,接着递归地进行右子树的前序遍历。


中序遍历:中序遍历中,我们首先递归地进行左子树的中序遍历,然后访问根节点,最后递归地进行右子树的中序遍历。


后序遍历:后序遍历中,我们首先递归地进行左子树的后序遍历,然后递归地进行右子树的后序遍历,最后访问根节点。

而这里呢我们又遇到了老朋友递归

问题不大

我们利用一棵树为例子

图中的这一棵树

以一为根

接下来我们先进行前序遍历

1.1.1前序遍历

前序遍历中先根后左右

●所以我们先去访问根1

●访问完根1后就访问左节点2

●接下来以2为根访问2的左节点3

●然后以3为根访问3的左节点,这是他的左节点为空,所以我们返回也就是开始进行递归

●递归到一后,开始进行访问1的右节点4

●访问到四就以4为根访问4的左节点5

●访问5后发现没有左节点就递归到4访问4的右节点

●访问6时没有左节点右节点就开始递归到4再到1

●最后访问结束

这里呢,我们用N代表空

那么访问完打印后应该是这样的

1 2 3 N N N 4 5 N N 6 N N

1.1.2中序遍历

讨论完前序遍历我们进行中序遍历

中序遍历讲的是先左后根最后右

还是利用这棵树

遍历顺序:

●先是访问左子树,1的左子树是2,2的则是3,3没有了左子树也就是空,返回3,然后在访问3的右子树,空,返回到2

这是返回的应该是

N 3 N

●回到2后访问2的左子树空,所以返回到1

N 3 N 2 N

●回到一就访问1的右子树4,然后到4的左子树5,在访问5的左子树空,这时返回到5

N 3 N 2 N 1 N 5 N

这时会有疑问,为什么没有四,不是先访问到4吗?

这里没有4的原因是,返回到1后应该访问它的右子树,而右子树中还有一个左子树5,所以应该先访问5,这里的5优先访问

●然后返回到4,访问4的右子树6,这里优先访问6的左子树,为空,返回到6,访问右子树,为空

N 3 N 2 N 1 N 5 N 4 N 6 N

1.1.3后序遍历

后序遍历则是先左后右最后根

遍历顺序:

还是以这棵树为例


●先访问1的左子树,到3时,他的左子树为空,右子树为空

N N 3

●返回到2后,右子树为空,访问根2,返回1

N N 3 N 2

●回到一后,访问一的右子树,同时优先访问右子树中的左子树也就是节点五,访问五的左子树,然后是右子树,然后是五

 N N 3 N 2 N N 5

●J返回到五后访问4的右子树6,然后访问6的左子树和右子树

N N 3 N 2 N N 5 N N 6

●访问完6后就返回访问4,然后访问1

N N 3 N 2 N N 5 N N 6 4 1

2.遍历代码的实现

2.1.树的实现

首先我们需要手搓一棵树

定义出来树的结构

并需要创建新的空间,所以这里包装一个函数

typedef struct BinTreeNode
{
	struct BinTreeNode* left;
	struct BinTreeNode* right;
	int val;
}BTNode;
BTNode* BuyBTNode(int val)
{
	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return NULL;
	}
	newnode->val = val;
	newnode->left = NULL;
	newnode->right = NULL;
	return newnode;
}
// 手搓一棵树
BTNode* CreateTree()
{
	BTNode* n1 = BuyBTNode(1);
	BTNode* n2 = BuyBTNode(2);
	BTNode* n3 = BuyBTNode(3);
	BTNode* n4 = BuyBTNode(4);
	BTNode* n5 = BuyBTNode(5);
	BTNode* n6 = BuyBTNode(6);

	n1->left = n2;
	n1->right = n4;
	n2->left = n3;
	n4->left = n5;
	n4->right = n6;

	return n1;
}

这样就形成了图形中的树

2.2前序遍历代码

前序遍历的话我们需要用到递归

首如果检测到节点为空,这样的话就打印N并返回

如果没有

那么递归继续往下

因为是前序遍历

所以先递归左然后再递归右

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

	printf("%d ", root->val);
	PreOrder(root->left);
	PreOrder(root->right);
}

2.3中序遍历代码

中序遍历和前序遍历的不同是前序遍历先根后左右,中序遍历则是先左后根最后右

所以,我们还是先遇到空返回N

没有则是返回左,打印根ra

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

	InOrder(root->left);
	printf("%d ", root->val);
	InOrder(root->right);
}

2.4后序遍历代码

后序遍历代码则是先左右最后根

所以

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

2.5测试的结果

3.获取节点个数

获取节点个数,正常情况下我们的思路是定义一个size

然后在遍历的时候进行++size

代码如下

int TreeSize(BTNode* root)
{
	static int size = 0;
	if (root == NULL)
		return 0;
	else
		++size;

	TreeSize(root->left);
	TreeSize(root->right);
	return size;
}

但这样会有一个缺点

我们没法去在这个函数里面重置我们的size

所以我们需要再主函数中

每调用完TreeSize函数,就需要重置一遍size

所以我们还有另外一个思路

直接去返回它的左节点和右节点,最后加一

利用递归的思想

代码如下

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

这样就非常巧妙的完成了节点的个数

标签:左子,遍历,右子,访问,二叉树,链式,数据结构,root,节点
From: https://blog.csdn.net/2301_80157147/article/details/136700365

相关文章

  • 代码随想录算法训练营第day17|110.平衡二叉树 、 257. 二叉树的所有路径 、404.左叶子
    目录a.110.平衡二叉树b.257.二叉树的所有路径 c.404.左叶子之和a.110.平衡二叉树力扣题目链接(opensnewwindow)给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。示例1......
  • 洛谷 P5018 对称二叉树
    题目背景NOIP2018普及组T4题目描述一棵有点权的有根树如果满足以下条件,则被轩轩称为对称二叉树:二叉树;将这棵树所有节点的左右子树交换,新树和原树对应位置的结构相同且点权相等。下图中节点内的数字为权值,节点外的 idid 表示节点编号。现在给出一棵二叉树,希望你找出......
  • P8681 [蓝桥杯 2019 省 AB] 完全二叉树的权值
    题目描述给定一棵包含N 个节点的完全二叉树,树上每个节点都有一个权值,按从上到下、从左到右的顺序依次是​,如下图所示: 现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点权值之和最大?如果有多个深度的权值和同为最大,请你输出其中最小的深度。注:根的深度是 1......
  • 二叉树
    节点类定义classTreeNode{privateStringvalue;privateTreeNodeleft;privateTreeNoderight;publicTreeNode(Stringvalue){this.value=value;this.left=null;this.right=null;}publicvoidsetLeft(Tr......
  • 归并排序、快速排序——左神数据结构与算法Day2学习笔记C++版本(持续更新)
    递归行为        利用递归求整个数组的最大值,代码如下。intfind_Max(inta[],intL,intR){if(L==R){returna[L];}intmid=L+((R-L)>>1);//mid是数组的中点intleftMax=find_Max(a,L,mid);intrightMax......
  • 第六章二叉树——二叉树的最大深度
    吾日三省吾身还记得的梦想吗正在努力实现它吗可以坚持下去吗目录吾日三省吾身力扣题号:104.二叉树的最大深度-力扣(LeetCode)题目描述:思路解法一:递归实现思路代码逻辑解释注意事项代码实现内存优化总结(╯°□°)╯︵┻━┻(⌐■_■)(¬‿¬)(´・ω・`)(͡°͜......
  • 【数据结构高阶】图
    目录一、图的基本概念二、 图的存储结构2.1邻接矩阵2.2.1 邻接矩阵存储模式的代码实现2.2.2 邻接矩阵存储的优缺点2.2邻接表2.2.1无向图的邻接表 2.2.2 有向图的邻接表  2.2.3 邻接表存储模式的代码实现2.2.4 邻接表存储的优缺点三、图的遍历3.1图的......
  • 236. 二叉树的最近公共祖先c
    /***Definitionforabinarytreenode.*structTreeNode{*intval;*structTreeNode*left;*structTreeNode*right;*};*/structTreeNode*lowestCommonAncestor(structTreeNode*root,structTreeNode*p,structTreeNode*q){......
  • leedcode-完全二叉树的节点个数
    自己写的,使用广度优先BFS,迭代:classSolution:defcountNodes(self,root:Optional[TreeNode])->int:#如果根节点为空,则树中节点数为0ifnotroot:return0#初始化队列,并将根节点放入队列中queue=[root]......
  • 14_学习日志_数据结构_冒泡排序_快速排序_插入排序
    #include<编织有意义的谎言,使我相信闭上眼再睁开眼时的世界是同一个>1.介绍    从后往前或者从前往后开始两两比较元素,使得最小数上浮或者最大数下沉为冒泡排序,快速排序利用分治思想,使得基准数左边都存放相对较小数,右边存放较大数,两边再按照同样的做法重复。插入排序......